summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2007-02-28 14:35:26 +0000
committerGerald Carter <jerry@samba.org>2007-02-28 14:35:26 +0000
commit80236f0d60ce013134c1ed5422d148e541f70a4f (patch)
treef71326fa71c0323e6b5d87b75b289d0608480f87 /source
parentf05f5dce39b11e937fb19270b7bcc888582edf35 (diff)
downloadsamba-80236f0d60ce013134c1ed5422d148e541f70a4f.tar.gz
samba-80236f0d60ce013134c1ed5422d148e541f70a4f.tar.xz
samba-80236f0d60ce013134c1ed5422d148e541f70a4f.zip
r21585: Start syncing the monster that will become 3.0.25pre1
Still todo: * release notes * few minor outstanding patches * additional idmap man pages
Diffstat (limited to 'source')
-rw-r--r--source/Makefile.in827
-rw-r--r--source/VERSION4
-rw-r--r--source/aclocal.m4519
-rw-r--r--source/auth/auth.c3
-rw-r--r--source/auth/auth_compat.c16
-rw-r--r--source/auth/auth_domain.c22
-rw-r--r--source/auth/auth_ntlmssp.c12
-rw-r--r--source/auth/auth_sam.c2
-rw-r--r--source/auth/auth_script.c8
-rw-r--r--source/auth/auth_server.c76
-rw-r--r--source/auth/auth_unix.c9
-rw-r--r--source/auth/auth_util.c298
-rw-r--r--source/auth/auth_winbind.c10
-rw-r--r--source/auth/pampass.c5
-rwxr-xr-xsource/autogen.sh14
-rw-r--r--source/client/client.c355
-rw-r--r--source/client/clitar.c49
-rwxr-xr-xsource/client/mount.cifs.c40
-rw-r--r--source/client/smbctool.c2
-rw-r--r--source/client/smbmount.c17
-rw-r--r--source/client/smbspool.c7
-rw-r--r--source/client/umount.cifs.c6
-rwxr-xr-xsource/configure.developer5
-rw-r--r--source/configure.in1318
-rw-r--r--source/groupdb/mapping.c661
-rw-r--r--source/groupdb/mapping.h26
-rw-r--r--source/groupdb/mapping_tdb.c690
-rw-r--r--source/include/ads.h35
-rw-r--r--source/include/ads_cldap.h9
-rw-r--r--source/include/ads_dns.h8
-rw-r--r--source/include/ads_protos.h95
-rw-r--r--source/include/adt_tree.h4
-rw-r--r--source/include/charset.h5
-rw-r--r--source/include/client.h12
-rw-r--r--source/include/core.h3
-rw-r--r--source/include/core/nterr.h1
-rw-r--r--source/include/dcerpc.h40
-rw-r--r--source/include/dlinklist.h62
-rw-r--r--source/include/event.h12
-rw-r--r--source/include/gpo.h22
-rw-r--r--source/include/idmap.h55
-rw-r--r--source/include/includes.h484
-rw-r--r--source/include/libmsrpc.h2
-rw-r--r--source/include/libsmb_internal.h17
-rw-r--r--source/include/libsmbclient.h16
-rw-r--r--source/include/local.h3
-rw-r--r--source/include/locking.h89
-rw-r--r--source/include/mangle.h12
-rw-r--r--source/include/mapping.h2
-rw-r--r--source/include/messages.h17
-rw-r--r--source/include/msdfs.h6
-rw-r--r--source/include/ndr.h1
-rw-r--r--source/include/nss_info.h92
-rw-r--r--source/include/nt_status.h40
-rw-r--r--source/include/ntdomain.h6
-rw-r--r--source/include/nterr.h5
-rw-r--r--source/include/ntlmssp.h7
-rw-r--r--source/include/passdb.h22
-rw-r--r--source/include/printing.h4
-rw-r--r--source/include/privileges.h4
-rw-r--r--source/include/reg_objects.h5
-rw-r--r--source/include/rpc_client.h4
-rw-r--r--source/include/rpc_dce.h2
-rw-r--r--source/include/rpc_dfs.h2
-rw-r--r--source/include/rpc_ds.h8
-rw-r--r--source/include/rpc_lsa.h2
-rw-r--r--source/include/rpc_misc.h33
-rw-r--r--source/include/rpc_netlogon.h30
-rw-r--r--source/include/rpc_perfcount.h33
-rw-r--r--source/include/rpc_perfcount_defs.h21
-rw-r--r--source/include/rpc_samr.h40
-rw-r--r--source/include/rpc_secdes.h64
-rwxr-xr-xsource/include/rpc_spoolss.h8
-rw-r--r--source/include/rpc_srvsvc.h6
-rw-r--r--source/include/rpc_wkssvc.h72
-rw-r--r--source/include/session.h3
-rw-r--r--source/include/smb.h306
-rw-r--r--source/include/smb_acls.h251
-rw-r--r--source/include/smb_macros.h46
-rw-r--r--source/include/smbldap.h4
-rw-r--r--source/include/smbprofile.h1057
-rw-r--r--source/include/socket_wrapper.h48
-rw-r--r--source/include/trans2.h45
-rw-r--r--source/include/util_tdb.h76
-rw-r--r--source/include/vfs.h147
-rw-r--r--source/include/vfs_macros.h359
-rw-r--r--source/iniparser/src/dictionary.c20
-rw-r--r--source/iniparser/src/iniparser.c19
-rw-r--r--source/iniparser/src/iniparser.h10
-rw-r--r--source/iniparser/src/strlib.c2
-rw-r--r--source/iniparser/src/strlib.h2
-rw-r--r--source/intl/lang_tdb.c2
-rw-r--r--source/lib/account_pol.c201
-rw-r--r--source/lib/adt_tree.c5
-rw-r--r--source/lib/afs.c7
-rw-r--r--source/lib/charcnv.c204
-rw-r--r--source/lib/data_blob.c35
-rw-r--r--source/lib/debug.c20
-rw-r--r--source/lib/display_sec.c10
-rw-r--r--source/lib/dmallocmsg.c14
-rw-r--r--source/lib/dprintf.c2
-rw-r--r--source/lib/dummysmbd.c20
-rw-r--r--source/lib/events.c284
-rw-r--r--source/lib/fault.c7
-rw-r--r--source/lib/gencache.c155
-rw-r--r--source/lib/getsmbpass.c183
-rw-r--r--source/lib/iconv.c7
-rw-r--r--source/lib/interface.c6
-rw-r--r--source/lib/interfaces.c49
-rw-r--r--source/lib/ldap_escape.c4
-rw-r--r--source/lib/messages.c293
-rw-r--r--source/lib/pam_errors.c7
-rw-r--r--source/lib/popt_common.c10
-rw-r--r--source/lib/privileges.c11
-rw-r--r--source/lib/readline.c4
-rw-r--r--source/lib/replace.c437
-rw-r--r--source/lib/replace/.checker_innocent4
-rw-r--r--source/lib/replace/Makefile.in60
-rw-r--r--source/lib/replace/README88
-rw-r--r--source/lib/replace/aclocal.m41
-rw-r--r--source/lib/replace/autoconf-2.60.m4197
-rwxr-xr-xsource/lib/replace/autogen.sh13
-rwxr-xr-xsource/lib/replace/config.guess1466
-rwxr-xr-xsource/lib/replace/config.sub1579
-rw-r--r--source/lib/replace/configure.ac22
-rw-r--r--source/lib/replace/dlfcn.c54
-rw-r--r--source/lib/replace/dlfcn.m420
-rw-r--r--source/lib/replace/getpass.c212
-rw-r--r--source/lib/replace/getpass.m417
-rwxr-xr-xsource/lib/replace/install-sh238
-rw-r--r--source/lib/replace/libreplace.m4355
-rw-r--r--source/lib/replace/libreplace_cc.m4167
-rw-r--r--source/lib/replace/libreplace_macros.m4308
-rw-r--r--source/lib/replace/repdir.m478
-rw-r--r--source/lib/replace/repdir_getdents.c167
-rw-r--r--source/lib/replace/repdir_getdirentries.c184
-rw-r--r--source/lib/replace/replace.c613
-rw-r--r--source/lib/replace/replace.h408
-rw-r--r--source/lib/replace/samba.m423
-rw-r--r--source/lib/replace/snprintf.c (renamed from source/lib/snprintf.c)146
-rw-r--r--source/lib/replace/system/README4
-rw-r--r--source/lib/replace/system/aio.h (renamed from source/smbwrapper/realcalls.c)35
-rw-r--r--source/lib/replace/system/capability.h41
-rw-r--r--source/lib/replace/system/config.m431
-rw-r--r--source/lib/replace/system/dir.h64
-rw-r--r--source/lib/replace/system/filesys.h170
-rw-r--r--source/lib/replace/system/glob.h33
-rw-r--r--source/lib/replace/system/iconv.h53
-rw-r--r--source/lib/replace/system/kerberos.h132
-rw-r--r--source/lib/replace/system/locale.h (renamed from source/tdb/tdbutil.h)32
-rw-r--r--source/lib/replace/system/network.h113
-rw-r--r--source/lib/replace/system/passwd.h91
-rw-r--r--source/lib/replace/system/printing.h46
-rw-r--r--source/lib/replace/system/readline.h48
-rw-r--r--source/lib/replace/system/select.h33
-rw-r--r--source/lib/replace/system/shmem.h55
-rw-r--r--source/lib/replace/system/syslog.h66
-rw-r--r--source/lib/replace/system/terminal.h42
-rw-r--r--source/lib/replace/system/time.h40
-rw-r--r--source/lib/replace/system/wait.h (renamed from source/lib/replace1.c)37
-rw-r--r--source/lib/replace/test/os2_delete.c115
-rw-r--r--source/lib/replace/test/shared_mmap.c68
-rw-r--r--source/lib/replace/test/testsuite.c481
-rw-r--r--source/lib/replace/timegm.c (renamed from source/lib/timegm.c)13
-rw-r--r--source/lib/replace/timegm.m41
-rw-r--r--source/lib/replace/win32.m420
-rw-r--r--source/lib/replace/win32_replace.h159
-rw-r--r--source/lib/secace.c14
-rw-r--r--source/lib/secacl.c8
-rw-r--r--source/lib/secdesc.c54
-rw-r--r--source/lib/sharesec.c50
-rw-r--r--source/lib/smbldap.c176
-rw-r--r--source/lib/socket_wrapper.c784
-rw-r--r--source/lib/socket_wrapper/config.m422
-rw-r--r--source/lib/socket_wrapper/socket_wrapper.c1596
-rw-r--r--source/lib/socket_wrapper/socket_wrapper.h133
-rw-r--r--source/lib/substitute.c197
-rw-r--r--source/lib/sysacls.c2938
-rw-r--r--source/lib/sysquotas_linux.c12
-rw-r--r--source/lib/system.c216
-rw-r--r--source/lib/system_smbd.c15
-rw-r--r--source/lib/talloc/Makefile.in71
-rw-r--r--source/lib/talloc/aclocal.m41
-rwxr-xr-xsource/lib/talloc/autogen.sh14
-rwxr-xr-xsource/lib/talloc/config.guess1466
-rw-r--r--source/lib/talloc/config.mk18
-rwxr-xr-xsource/lib/talloc/config.sub1579
-rw-r--r--source/lib/talloc/configure.ac18
-rwxr-xr-xsource/lib/talloc/install-sh238
-rw-r--r--source/lib/talloc/libtalloc.m427
-rw-r--r--source/lib/talloc/talloc.3.xml718
-rw-r--r--source/lib/talloc/talloc.c (renamed from source/lib/talloc.c)863
-rw-r--r--source/lib/talloc/talloc.h (renamed from source/include/talloc.h)95
-rw-r--r--source/lib/talloc/talloc.pc.in10
-rw-r--r--source/lib/talloc/talloc_guide.txt653
-rw-r--r--source/lib/talloc/testsuite.c1061
-rw-r--r--source/lib/talloc/web/index.html49
-rw-r--r--source/lib/tallocmsg.c62
-rw-r--r--source/lib/talloctort.c844
-rw-r--r--source/lib/time.c1550
-rw-r--r--source/lib/util.c161
-rw-r--r--source/lib/util_file.c249
-rw-r--r--source/lib/util_pw.c4
-rw-r--r--source/lib/util_seaccess.c10
-rw-r--r--source/lib/util_sec.c8
-rw-r--r--source/lib/util_sid.c39
-rw-r--r--source/lib/util_sock.c2
-rw-r--r--source/lib/util_str.c318
-rw-r--r--source/lib/util_tdb.c (renamed from source/tdb/tdbutil.c)325
-rw-r--r--source/lib/util_unistr.c20
-rw-r--r--source/lib/util_uuid.c16
-rw-r--r--source/lib/xfile.c2
-rw-r--r--source/libaddns/addns.h32
-rw-r--r--source/libaddns/dns.h505
-rw-r--r--source/libaddns/dnserr.h89
-rw-r--r--source/libaddns/dnsgss.c344
-rw-r--r--source/libaddns/dnsmarshall.c531
-rw-r--r--source/libaddns/dnsrecord.c413
-rw-r--r--source/libaddns/dnssock.c374
-rw-r--r--source/libaddns/dnsutils.c153
-rw-r--r--source/libads/ads_status.c32
-rw-r--r--source/libads/ads_struct.c32
-rw-r--r--source/libads/ads_utils.c2
-rw-r--r--source/libads/authdata.c4
-rw-r--r--source/libads/cldap.c10
-rw-r--r--source/libads/disp_sec.c12
-rw-r--r--source/libads/dns.c425
-rw-r--r--source/libads/kerberos.c309
-rw-r--r--source/libads/kerberos_keytab.c14
-rw-r--r--source/libads/kerberos_verify.c106
-rw-r--r--source/libads/krb5_errs.c4
-rw-r--r--source/libads/krb5_setpw.c4
-rw-r--r--source/libads/ldap.c560
-rw-r--r--source/libads/ldap_printer.c7
-rw-r--r--source/libads/ldap_schema.c85
-rw-r--r--source/libads/ldap_user.c3
-rw-r--r--source/libads/ldap_utils.c49
-rw-r--r--source/libads/sasl.c49
-rw-r--r--source/libgpo/gpo_fetch.c194
-rw-r--r--source/libgpo/gpo_filesync.c225
-rw-r--r--source/libgpo/gpo_ldap.c (renamed from source/libads/gpo.c)129
-rw-r--r--source/libgpo/gpo_parse.c299
-rw-r--r--source/libgpo/gpo_util.c (renamed from source/libads/gpo_util.c)198
-rw-r--r--source/libmsrpc/cac_lsarpc.c2092
-rw-r--r--source/libmsrpc/cac_samr.c4050
-rw-r--r--source/libmsrpc/cac_svcctl.c854
-rw-r--r--source/libmsrpc/cac_winreg.c1729
-rw-r--r--source/libmsrpc/libmsrpc.c497
-rw-r--r--source/libmsrpc/libmsrpc_internal.c1256
-rw-r--r--source/librpc/gen_ndr/cli_wkssvc.c964
-rw-r--r--source/librpc/gen_ndr/cli_wkssvc.h35
-rw-r--r--source/librpc/gen_ndr/ndr_notify.c242
-rw-r--r--source/librpc/gen_ndr/ndr_notify.h20
-rw-r--r--source/librpc/gen_ndr/ndr_srvsvc.h312
-rw-r--r--source/librpc/gen_ndr/ndr_wkssvc.c4787
-rw-r--r--source/librpc/gen_ndr/ndr_wkssvc.h133
-rw-r--r--source/librpc/gen_ndr/notify.h33
-rw-r--r--source/librpc/gen_ndr/security.h1
-rw-r--r--source/librpc/gen_ndr/srv_wkssvc.c2073
-rw-r--r--source/librpc/gen_ndr/srv_wkssvc.h37
-rw-r--r--source/librpc/gen_ndr/srvsvc.h1753
-rw-r--r--source/librpc/gen_ndr/svcctl.h738
-rw-r--r--source/librpc/gen_ndr/wkssvc.h505
-rw-r--r--source/librpc/ndr/libndr.h297
-rw-r--r--source/librpc/ndr/misc.h37
-rw-r--r--source/librpc/ndr/ndr.c964
-rw-r--r--source/librpc/ndr/ndr_basic.c803
-rw-r--r--source/librpc/ndr/ndr_misc.c272
-rw-r--r--source/librpc/ndr/ndr_sec.h35
-rw-r--r--source/librpc/ndr/ndr_sec_helper.c903
-rw-r--r--source/librpc/ndr/ndr_string.c620
-rw-r--r--source/librpc/ndr/security.h253
-rw-r--r--source/librpc/ndr/sid.c252
-rw-r--r--source/libsmb/asn1.c19
-rw-r--r--source/libsmb/cliconnect.c279
-rw-r--r--source/libsmb/clidfs.c16
-rw-r--r--source/libsmb/clidgram.c5
-rw-r--r--source/libsmb/clientgen.c45
-rw-r--r--source/libsmb/clierror.c11
-rw-r--r--source/libsmb/clifile.c58
-rw-r--r--source/libsmb/clifsinfo.c57
-rw-r--r--source/libsmb/clikrb5.c156
-rw-r--r--source/libsmb/clilist.c44
-rw-r--r--source/libsmb/clirap.c61
-rw-r--r--source/libsmb/clirap2.c58
-rw-r--r--source/libsmb/clireadwrite.c4
-rw-r--r--source/libsmb/clispnego.c6
-rw-r--r--source/libsmb/clistr.c4
-rw-r--r--source/libsmb/clitrans.c8
-rw-r--r--source/libsmb/conncache.c28
-rw-r--r--source/libsmb/errormap.c9
-rw-r--r--source/libsmb/gpo.c167
-rw-r--r--source/libsmb/libsmb_cache.c11
-rw-r--r--source/libsmb/libsmbclient.c978
-rw-r--r--source/libsmb/namecache.c44
-rw-r--r--source/libsmb/namequery.c176
-rw-r--r--source/libsmb/namequery_dc.c96
-rw-r--r--source/libsmb/nterr.c17
-rw-r--r--source/libsmb/ntlm_check.c2
-rw-r--r--source/libsmb/ntlmssp.c118
-rw-r--r--source/libsmb/ntlmssp_sign.c2
-rw-r--r--source/libsmb/passchange.c143
-rw-r--r--source/libsmb/samlogon_cache.c3
-rw-r--r--source/libsmb/smb_share_modes.c19
-rw-r--r--source/libsmb/smb_signing.c15
-rw-r--r--source/libsmb/smbdes.c6
-rw-r--r--source/libsmb/smbencrypt.c68
-rw-r--r--source/libsmb/trustdom_cache.c46
-rw-r--r--source/libsmb/trusts_util.c2
-rw-r--r--source/locking/brlock.c524
-rw-r--r--source/locking/locking.c302
-rw-r--r--source/locking/posix.c1309
-rw-r--r--source/modules/README-gpfs-acl.txt82
-rw-r--r--source/modules/README.nfs4acls.txt82
-rw-r--r--source/modules/charset_macosxfs.c4
-rw-r--r--source/modules/gpfs.c236
-rw-r--r--source/modules/nfs4_acls.c668
-rw-r--r--source/modules/nfs4_acls.h146
-rw-r--r--source/modules/vfs_afsacl.c22
-rw-r--r--source/modules/vfs_aixacl.c216
-rw-r--r--source/modules/vfs_aixacl2.c538
-rw-r--r--source/modules/vfs_aixacl_util.c297
-rw-r--r--source/modules/vfs_audit.c61
-rw-r--r--source/modules/vfs_cacheprime.c201
-rw-r--r--source/modules/vfs_cap.c125
-rw-r--r--source/modules/vfs_catia.c85
-rw-r--r--source/modules/vfs_commit.c190
-rw-r--r--source/modules/vfs_default.c1389
-rw-r--r--source/modules/vfs_default_quota.c17
-rw-r--r--source/modules/vfs_expand_msdfs.c14
-rw-r--r--source/modules/vfs_extd_audit.c61
-rw-r--r--source/modules/vfs_fake_perms.c5
-rw-r--r--source/modules/vfs_full_audit.c375
-rw-r--r--source/modules/vfs_gpfs.c674
-rw-r--r--source/modules/vfs_hpuxacl.c105
-rw-r--r--source/modules/vfs_irixacl.c105
-rw-r--r--source/modules/vfs_netatalk.c63
-rw-r--r--source/modules/vfs_notify_fam.c302
-rw-r--r--source/modules/vfs_posixacl.c392
-rw-r--r--source/modules/vfs_prealloc.c215
-rw-r--r--source/modules/vfs_readonly.c6
-rw-r--r--source/modules/vfs_recycle.c67
-rw-r--r--source/modules/vfs_shadow_copy.c29
-rw-r--r--source/modules/vfs_solarisacl.c789
-rw-r--r--source/modules/vfs_tru64acl.c505
-rw-r--r--source/modules/weird.c1
-rw-r--r--source/nmbd/nmbd.c20
-rw-r--r--source/nmbd/nmbd_browserdb.c3
-rw-r--r--source/nmbd/nmbd_elections.c2
-rw-r--r--source/nmbd/nmbd_processlogon.c2
-rw-r--r--source/nmbd/nmbd_synclists.c34
-rw-r--r--source/nmbd/nmbd_winsserver.c4
-rw-r--r--source/nsswitch/idmap.c1310
-rw-r--r--source/nsswitch/idmap_ad.c816
-rw-r--r--source/nsswitch/idmap_cache.c530
-rw-r--r--source/nsswitch/idmap_ldap.c1364
-rw-r--r--source/nsswitch/idmap_nss.c215
-rw-r--r--source/nsswitch/idmap_passdb.c131
-rw-r--r--source/nsswitch/idmap_rid.c298
-rw-r--r--source/nsswitch/idmap_tdb.c1214
-rw-r--r--source/nsswitch/idmap_util.c160
-rw-r--r--source/nsswitch/nss_info.c266
-rw-r--r--source/nsswitch/nss_info_template.c85
-rw-r--r--source/nsswitch/pam_winbind.c1489
-rw-r--r--source/nsswitch/pam_winbind.h73
-rw-r--r--source/nsswitch/wb_client.c310
-rw-r--r--source/nsswitch/wb_common.c10
-rw-r--r--source/nsswitch/wbinfo.c137
-rw-r--r--source/nsswitch/winbind_nss.h10
-rw-r--r--source/nsswitch/winbind_nss_aix.c7
-rw-r--r--source/nsswitch/winbind_nss_config.h54
-rw-r--r--source/nsswitch/winbind_nss_linux.c192
-rw-r--r--source/nsswitch/winbind_nss_netbsd.c405
-rw-r--r--source/nsswitch/winbind_nss_netbsd.h42
-rw-r--r--source/nsswitch/winbindd.c129
-rw-r--r--source/nsswitch/winbindd.h36
-rw-r--r--source/nsswitch/winbindd_ads.c189
-rw-r--r--source/nsswitch/winbindd_async.c1004
-rw-r--r--source/nsswitch/winbindd_cache.c297
-rw-r--r--source/nsswitch/winbindd_ccache_access.c284
-rw-r--r--source/nsswitch/winbindd_cm.c842
-rw-r--r--source/nsswitch/winbindd_cred_cache.c686
-rw-r--r--source/nsswitch/winbindd_creds.c7
-rw-r--r--source/nsswitch/winbindd_dual.c259
-rw-r--r--source/nsswitch/winbindd_group.c391
-rw-r--r--source/nsswitch/winbindd_misc.c12
-rw-r--r--source/nsswitch/winbindd_nss.h76
-rw-r--r--source/nsswitch/winbindd_pam.c738
-rw-r--r--source/nsswitch/winbindd_passdb.c213
-rw-r--r--source/nsswitch/winbindd_reconnect.c29
-rw-r--r--source/nsswitch/winbindd_rpc.c144
-rw-r--r--source/nsswitch/winbindd_sid.c446
-rw-r--r--source/nsswitch/winbindd_user.c108
-rw-r--r--source/nsswitch/winbindd_util.c404
-rw-r--r--source/nsswitch/winbindd_wins.c2
-rw-r--r--source/nsswitch/wins.c5
-rw-r--r--source/param/loadparm.c283
-rw-r--r--source/param/params.c1
-rw-r--r--source/passdb/login_cache.c2
-rw-r--r--source/passdb/lookup_sid.c443
-rw-r--r--source/passdb/passdb.c45
-rw-r--r--source/passdb/pdb_get_set.c113
-rw-r--r--source/passdb/pdb_interface.c189
-rw-r--r--source/passdb/pdb_ldap.c152
-rw-r--r--source/passdb/pdb_nds.c11
-rw-r--r--source/passdb/pdb_smbpasswd.c76
-rw-r--r--source/passdb/pdb_tdb.c43
-rw-r--r--source/passdb/secrets.c253
-rw-r--r--source/po/fi.msg611
-rw-r--r--source/popt/findme.c4
-rw-r--r--source/popt/popt.c115
-rw-r--r--source/printing/notify.c8
-rw-r--r--source/printing/nt_printing.c248
-rw-r--r--source/printing/print_cups.c72
-rw-r--r--source/printing/print_generic.c10
-rw-r--r--source/printing/print_iprint.c6
-rw-r--r--source/printing/print_test.c82
-rw-r--r--source/printing/printfsp.c20
-rw-r--r--source/printing/printing.c71
-rw-r--r--source/profile/profile.c193
-rw-r--r--source/python/py_lsa.c2
-rw-r--r--source/python/py_smb.c6
-rw-r--r--source/registry/reg_cachehook.c4
-rw-r--r--source/registry/reg_db.c43
-rw-r--r--source/registry/reg_frontend.c8
-rw-r--r--source/registry/reg_objects.c9
-rw-r--r--source/registry/reg_perfcount.c37
-rw-r--r--source/registry/reg_printing.c10
-rw-r--r--source/registry/regfio.c7
-rw-r--r--source/rpc_client/cli_lsarpc.c6
-rw-r--r--source/rpc_client/cli_netlogon.c15
-rw-r--r--source/rpc_client/cli_pipe.c10
-rw-r--r--source/rpc_client/cli_reg.c2
-rw-r--r--source/rpc_client/cli_samr.c49
-rw-r--r--source/rpc_client/cli_spoolss.c7
-rw-r--r--source/rpc_client/cli_wkssvc.c68
-rw-r--r--source/rpc_client/ndr.c92
-rw-r--r--source/rpc_parse/parse_buffer.c3
-rw-r--r--source/rpc_parse/parse_dfs.c2
-rw-r--r--source/rpc_parse/parse_eventlog.c2
-rw-r--r--source/rpc_parse/parse_lsa.c14
-rw-r--r--source/rpc_parse/parse_misc.c57
-rw-r--r--source/rpc_parse/parse_net.c21
-rw-r--r--source/rpc_parse/parse_ntsvcs.c4
-rw-r--r--source/rpc_parse/parse_prs.c50
-rw-r--r--source/rpc_parse/parse_samr.c115
-rw-r--r--source/rpc_parse/parse_sec.c32
-rw-r--r--source/rpc_parse/parse_spoolss.c54
-rw-r--r--source/rpc_parse/parse_svcctl.c14
-rw-r--r--source/rpc_parse/parse_wks.c178
-rw-r--r--source/rpc_server/srv_eventlog_lib.c2
-rw-r--r--source/rpc_server/srv_eventlog_nt.c2
-rw-r--r--source/rpc_server/srv_lsa_hnd.c18
-rw-r--r--source/rpc_server/srv_lsa_nt.c10
-rw-r--r--source/rpc_server/srv_netlog_nt.c2
-rw-r--r--source/rpc_server/srv_pipe.c4
-rw-r--r--source/rpc_server/srv_reg_nt.c3
-rw-r--r--source/rpc_server/srv_samr_nt.c320
-rw-r--r--source/rpc_server/srv_samr_util.c171
-rwxr-xr-xsource/rpc_server/srv_spoolss.c18
-rw-r--r--source/rpc_server/srv_spoolss_nt.c76
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c113
-rw-r--r--source/rpc_server/srv_svcctl_nt.c2
-rw-r--r--source/rpc_server/srv_wkssvc.c78
-rw-r--r--source/rpc_server/srv_wkssvc_nt.c352
-rw-r--r--source/rpcclient/cmd_lsarpc.c10
-rw-r--r--source/rpcclient/cmd_netlogon.c25
-rw-r--r--source/rpcclient/cmd_reg.c996
-rw-r--r--source/rpcclient/cmd_samr.c140
-rw-r--r--source/rpcclient/cmd_spoolss.c10
-rw-r--r--source/rpcclient/rpcclient.c2
-rw-r--r--source/sam/idmap.c403
-rw-r--r--source/sam/idmap_ad.c380
-rw-r--r--source/sam/idmap_ldap.c537
-rw-r--r--source/sam/idmap_rid.c560
-rw-r--r--source/sam/idmap_smbldap.c443
-rw-r--r--source/sam/idmap_tdb.c637
-rw-r--r--source/sam/idmap_util.c112
-rw-r--r--source/sam/nss_info.c111
-rwxr-xr-xsource/script/installman.sh1
-rwxr-xr-xsource/script/installswat.sh10
-rw-r--r--source/script/mkbuildoptions.awk1
-rw-r--r--source/script/mkproto.awk19
-rwxr-xr-xsource/script/mkproto.sh2
-rw-r--r--source/script/tests/gdb_backtrace100
-rwxr-xr-xsource/script/tests/selftest.sh78
-rw-r--r--source/script/tests/test_functions.sh75
-rwxr-xr-xsource/script/tests/test_groupmap.sh214
-rwxr-xr-xsource/script/tests/test_local_s3.sh23
-rwxr-xr-xsource/script/tests/test_posix_s3.sh20
-rwxr-xr-xsource/script/tests/test_smbclient_s3.sh10
-rwxr-xr-xsource/script/tests/test_smbtorture_s3.sh6
-rwxr-xr-xsource/script/tests/tests_all.sh1
-rw-r--r--source/services/svc_winreg.c1
-rw-r--r--source/smbd/aio.c291
-rw-r--r--source/smbd/blocking.c499
-rw-r--r--source/smbd/change_trust_pw.c4
-rw-r--r--source/smbd/chgpasswd.c45
-rw-r--r--source/smbd/close.c312
-rw-r--r--source/smbd/conn.c36
-rw-r--r--source/smbd/connection.c169
-rw-r--r--source/smbd/dfree.c2
-rw-r--r--source/smbd/dir.c109
-rw-r--r--source/smbd/dmapi.c21
-rw-r--r--source/smbd/dosmode.c52
-rw-r--r--source/smbd/error.c62
-rw-r--r--source/smbd/fake_file.c27
-rw-r--r--source/smbd/fileio.c2
-rw-r--r--source/smbd/filename.c229
-rw-r--r--source/smbd/files.c75
-rw-r--r--source/smbd/ipc.c11
-rw-r--r--source/smbd/lanman.c51
-rw-r--r--source/smbd/mangle.c28
-rw-r--r--source/smbd/mangle_hash.c18
-rw-r--r--source/smbd/mangle_hash2.c46
-rw-r--r--source/smbd/mangle_map.c4
-rw-r--r--source/smbd/message.c3
-rw-r--r--source/smbd/msdfs.c84
-rw-r--r--source/smbd/negprot.c103
-rw-r--r--source/smbd/notify.c520
-rw-r--r--source/smbd/notify_fam.c463
-rw-r--r--source/smbd/notify_hash.c261
-rw-r--r--source/smbd/notify_inotify.c425
-rw-r--r--source/smbd/notify_internal.c686
-rw-r--r--source/smbd/notify_kernel.c247
-rw-r--r--source/smbd/ntquotas.c2
-rw-r--r--source/smbd/nttrans.c585
-rw-r--r--source/smbd/open.c945
-rw-r--r--source/smbd/oplock.c72
-rw-r--r--source/smbd/oplock_irix.c65
-rw-r--r--source/smbd/oplock_linux.c58
-rw-r--r--source/smbd/password.c45
-rw-r--r--source/smbd/pipes.c17
-rw-r--r--source/smbd/posix_acls.c158
-rw-r--r--source/smbd/process.c210
-rw-r--r--source/smbd/quotas.c30
-rw-r--r--source/smbd/reply.c2063
-rw-r--r--source/smbd/sec_ctx.c23
-rw-r--r--source/smbd/server.c198
-rw-r--r--source/smbd/service.c178
-rw-r--r--source/smbd/session.c45
-rw-r--r--source/smbd/sesssetup.c279
-rw-r--r--source/smbd/share_access.c7
-rw-r--r--source/smbd/statcache.c42
-rw-r--r--source/smbd/statvfs.c4
-rw-r--r--source/smbd/trans2.c3125
-rw-r--r--source/smbd/uid.c14
-rw-r--r--source/smbd/vfs-wrap.c1104
-rw-r--r--source/smbd/vfs.c317
-rw-r--r--source/smbwrapper/PORTING77
-rw-r--r--source/smbwrapper/README94
-rw-r--r--source/smbwrapper/realcalls.h276
-rw-r--r--source/smbwrapper/shared.c203
-rw-r--r--source/smbwrapper/smbsh.c128
-rw-r--r--source/smbwrapper/smbsh.in54
-rw-r--r--source/smbwrapper/smbw.c1562
-rw-r--r--source/smbwrapper/smbw.h71
-rw-r--r--source/smbwrapper/smbw_cache.c205
-rw-r--r--source/smbwrapper/smbw_dir.c689
-rw-r--r--source/smbwrapper/smbw_stat.c270
-rw-r--r--source/smbwrapper/wrapped.c705
-rw-r--r--source/tdb/Makefile32
-rw-r--r--source/tdb/Makefile.in89
-rw-r--r--source/tdb/aclocal.m41
-rwxr-xr-xsource/tdb/autogen.sh14
-rw-r--r--source/tdb/common/dump.c138
-rw-r--r--source/tdb/common/error.c58
-rw-r--r--source/tdb/common/freelist.c331
-rw-r--r--source/tdb/common/freelistcheck.c108
-rw-r--r--source/tdb/common/io.c427
-rw-r--r--source/tdb/common/lock.c412
-rw-r--r--source/tdb/common/open.c455
-rw-r--r--source/tdb/common/tdb.c482
-rw-r--r--source/tdb/common/tdb_private.h211
-rw-r--r--source/tdb/common/tdbback.c (renamed from source/tdb/tdbback.c)13
-rw-r--r--source/tdb/common/transaction.c1054
-rw-r--r--source/tdb/common/traverse.c335
-rw-r--r--source/tdb/config.m458
-rw-r--r--source/tdb/config.mk70
-rw-r--r--source/tdb/configure.in13
-rw-r--r--source/tdb/docs/README (renamed from source/tdb/README)72
-rw-r--r--source/tdb/docs/tdb.magic (renamed from source/tdb/tdb.magic)0
-rw-r--r--source/tdb/include/tdb.h151
-rw-r--r--source/tdb/include/tdbback.h (renamed from source/tdb/tdbback.h)2
-rw-r--r--source/tdb/include/tdbconfig.h.in58
-rw-r--r--source/tdb/spinlock.c472
-rw-r--r--source/tdb/spinlock.h59
-rw-r--r--source/tdb/swig/Tdb.py116
-rw-r--r--source/tdb/swig/tdb.i (renamed from source/tdb/tdb.h)180
-rw-r--r--source/tdb/tdb.c2127
-rw-r--r--source/tdb/tdb.pc.in10
-rw-r--r--source/tdb/tdbtorture.c227
-rw-r--r--source/tdb/tools/tdbbackup.c (renamed from source/tdb/tdbbackup.c)9
-rw-r--r--source/tdb/tools/tdbdump.c (renamed from source/tdb/tdbdump.c)0
-rw-r--r--source/tdb/tools/tdbtest.c (renamed from source/tdb/tdbtest.c)62
-rw-r--r--source/tdb/tools/tdbtool.c (renamed from source/tdb/tdbtool.c)0
-rw-r--r--source/tdb/tools/tdbtorture.c318
-rw-r--r--source/torture/cmd_vfs.c24
-rw-r--r--source/torture/denytest.c12
-rw-r--r--source/torture/locktest.c31
-rw-r--r--source/torture/locktest2.c6
-rw-r--r--source/torture/mangle_test.c2
-rw-r--r--source/torture/masktest.c23
-rw-r--r--source/torture/msgtest.c49
-rw-r--r--source/torture/nbio.c4
-rw-r--r--source/torture/nsstest.c55
-rw-r--r--source/torture/pdbtest.c392
-rw-r--r--source/torture/rpctorture.c2
-rw-r--r--source/torture/scanner.c16
-rw-r--r--source/torture/torture.c442
-rw-r--r--source/torture/utable.c8
-rw-r--r--source/torture/vfstest.c23
-rw-r--r--source/utils/debug2html.c4
-rw-r--r--source/utils/debugparse.c1
-rw-r--r--source/utils/eventlogadm.c4
-rw-r--r--source/utils/log2pcaphex.c16
-rw-r--r--source/utils/net.c56
-rw-r--r--source/utils/net_ads.c637
-rw-r--r--source/utils/net_ads_gpo.c132
-rw-r--r--source/utils/net_cache.c43
-rw-r--r--source/utils/net_dns.c182
-rw-r--r--source/utils/net_domain.c6
-rw-r--r--source/utils/net_groupmap.c21
-rw-r--r--source/utils/net_idmap.c381
-rw-r--r--source/utils/net_lookup.c37
-rw-r--r--source/utils/net_rap.c30
-rw-r--r--source/utils/net_rpc.c35
-rw-r--r--source/utils/net_rpc_rights.c4
-rw-r--r--source/utils/net_rpc_samsync.c496
-rw-r--r--source/utils/net_rpc_service.c2
-rw-r--r--source/utils/net_sam.c223
-rw-r--r--source/utils/net_time.c10
-rw-r--r--source/utils/net_usershare.c18
-rw-r--r--source/utils/net_util.c4
-rw-r--r--source/utils/netlookup.c6
-rw-r--r--source/utils/ntlm_auth.c506
-rw-r--r--source/utils/ntlm_auth_diagnostics.c10
-rw-r--r--source/utils/pdbedit.c113
-rw-r--r--source/utils/profiles.c68
-rw-r--r--source/utils/sharesec.c607
-rw-r--r--source/utils/smbcacls.c72
-rw-r--r--source/utils/smbcontrol.c48
-rw-r--r--source/utils/smbcquotas.c4
-rw-r--r--source/utils/smbget.c26
-rw-r--r--source/utils/status.c397
-rw-r--r--source/utils/status_profile.c544
-rw-r--r--source/web/diagnose.c10
-rw-r--r--source/web/neg_lang.c4
-rw-r--r--source/web/statuspage.c7
-rw-r--r--source/web/swat.c2
650 files changed, 95748 insertions, 43397 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index 348893552f8..4de8f74082c 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -10,6 +10,7 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
+datarootdir=@datarootdir@
selftest_prefix=@selftest_prefix@
smbtorture4_path=@smbtorture4_path@
@@ -20,11 +21,12 @@ SHLD=@SHLD@
CFLAGS=@CFLAGS@
CPPFLAGS=-DHAVE_CONFIG_H @CPPFLAGS@
EXEEXT=@EXEEXT@
-LDFLAGS=@LDFLAGS@
+LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@
AR=@AR@
LDSHFLAGS=@LDSHFLAGS@ @LDFLAGS@
WINBIND_NSS_LDSHFLAGS=@WINBIND_NSS_LDSHFLAGS@ @LDFLAGS@
AWK=@AWK@
+PICFLAG=@PICFLAG@
DYNEXP=@DYNEXP@
PYTHON=@PYTHON@
PERL=@PERL@
@@ -39,6 +41,7 @@ IDMAP_LIBS=@IDMAP_LIBS@
KRB5LIBS=@KRB5_LIBS@
LDAP_LIBS=@LDAP_LIBS@
NSCD_LIBS=@NSCD_LIBS@
+UUID_LIBS=@UUID_LIBS@
INSTALLCMD=@INSTALL@
INSTALLLIBCMD_SH=@INSTALLLIBCMD_SH@
@@ -115,16 +118,20 @@ LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@
LIBSMBSHAREMODES_MAJOR=0
LIBSMBSHAREMODES_MINOR=2
-FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_
+LIBADDNS=bin/libaddns.a @LIBADDNS_SHARED@
+LIBADDNS_MAJOR=0
+LIBADDNS_MINOR=1
+
+FLAGS1 = $(CFLAGS) @FLAGS1@ @SAMBA_CPPFLAGS@ $(CPPFLAGS)
FLAGS2 =
FLAGS3 =
FLAGS4 =
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4)
-FLAGS = $(ISA) $(FLAGS5)
+FLAGS = $(ISA) $(FLAGS5) -I$(srcdir)/lib -D_SAMBA_BUILD_=3
PASSWD_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" -DPRIVATE_DIR=\"$(PRIVATE_DIR)\"
PATH_FLAGS1 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DSBINDIR=\"$(SBINDIR)\"
-PATH_FLAGS2 = $(PATH_FLAGS1) -DBINDIR=\"$(BINDIR)\" -DDRIVERFILE=\"$(DRIVERFILE)\"
+PATH_FLAGS2 = $(PATH_FLAGS1) -DBINDIR=\"$(BINDIR)\"
PATH_FLAGS3 = $(PATH_FLAGS2) -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"
PATH_FLAGS4 = $(PATH_FLAGS3) -DSWATDIR=\"$(SWATDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DPIDDIR=\"$(PIDDIR)\"
PATH_FLAGS5 = $(PATH_FLAGS4) -DLIBDIR=\"$(LIBDIR)\" \
@@ -149,14 +156,16 @@ BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
- bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@
+ bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ \
+ bin/pdbtest@EXEEXT@ bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@
BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@
-EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ bin/talloctort@EXEEXT@ \
- bin/log2pcap@EXEEXT@
+EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ \
+ bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@ \
+ bin/log2pcap@EXEEXT@ bin/sharesec@EXEEXT@
-SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ @LIBMSRPC@
+SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ @LIBMSRPC@ @LIBADDNS@
PAM_MODULES = @PAM_MODULES@
@@ -168,15 +177,19 @@ RPC_MODULES = @RPC_MODULES@
IDMAP_MODULES = @IDMAP_MODULES@
CHARSET_MODULES = @CHARSET_MODULES@
AUTH_MODULES = @AUTH_MODULES@
-MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES)
+NSS_INFO_MODULES = @NSS_INFO_MODULES@
+MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) \
+ $(CHARSET_MODULES) $(AUTH_MODULES) $(NSS_INFO_MODULES)
######################################################################
# object file lists
######################################################################
-TDBBASE_OBJ = tdb/tdb.o tdb/spinlock.o
+TDBBASE_OBJ = tdb/common/tdb.o tdb/common/dump.o tdb/common/error.o \
+ tdb/common/freelist.o tdb/common/freelistcheck.o tdb/common/io.o tdb/common/lock.o \
+ tdb/common/open.o tdb/common/transaction.o tdb/common/traverse.o
-TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o tdb/tdbback.o
+TDB_OBJ = $(TDBBASE_OBJ) lib/util_tdb.o tdb/common/tdbback.o
SMBLDAP_OBJ = @SMBLDAP@ @SMBLDAPUTIL@
@@ -184,8 +197,6 @@ VERSION_OBJ = lib/version.o
DOSERR_OBJ = libsmb/doserr.o
-SNPRINTF_OBJ = lib/snprintf.o
-
WBCOMMON_OBJ = nsswitch/wb_common.o
AFS_OBJ = lib/afs.o
@@ -198,22 +209,40 @@ ERRORMAP_OBJ = libsmb/errormap.o
PASSCHANGE_OBJ = libsmb/passchange.o
-SOCKET_WRAPPER_OBJ = lib/socket_wrapper.o
+LIBNDR_OBJ = librpc/ndr/ndr_basic.o librpc/ndr/ndr.o librpc/ndr/ndr_misc.o \
+ librpc/ndr/ndr_sec_helper.o librpc/ndr/ndr_string.o librpc/ndr/sid.o \
+ rpc_client/ndr.o
+
+LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o librpc/gen_ndr/ndr_notify.o
RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o
-LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
- lib/getsmbpass.o lib/interface.o lib/md4.o \
- lib/interfaces.o lib/pidfile.o lib/replace.o lib/replace1.o lib/repdir.o lib/timegm.o \
- lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
+# this includes only the low level parse code, not stuff
+# that requires knowledge of security contexts
+RPC_PARSE_OBJ1 = $(RPC_PARSE_OBJ0) rpc_parse/parse_sec.o
+
+RPC_PARSE_OBJ2 = rpc_parse/parse_rpc.o rpc_parse/parse_net.o rpc_parse/parse_srv.o
+
+LIBREPLACE_OBJ = @LIBREPLACE_OBJS@
+
+SOCKET_WRAPPER_OBJ = @SOCKET_WRAPPER_OBJS@
+
+TALLOC_OBJ = lib/talloc/talloc.o
+
+LIB_WITHOUT_PROTO_OBJ = $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) $(TALLOC_OBJ)
+
+LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
+ lib/interface.o lib/md4.o \
+ lib/interfaces.o lib/pidfile.o \
+ lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
lib/ufc.o lib/genrand.o lib/username.o \
lib/util_pw.o lib/access.o lib/smbrun.o \
- lib/bitmap.o lib/crc32.o $(SNPRINTF_OBJ) lib/dprintf.o \
+ lib/bitmap.o lib/crc32.o lib/dprintf.o \
lib/xfile.o lib/wins_srv.o \
lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
lib/util_unistr.o lib/util_file.o lib/data_blob.o \
lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \
- lib/talloc.o lib/substitute.o lib/fsusage.o \
+ lib/substitute.o lib/fsusage.o \
lib/ms_fnmatch.o lib/select.o lib/messages.o \
lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \
lib/md5.o lib/hmacmd5.o lib/arc4.o lib/iconv.o \
@@ -221,9 +250,11 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/pam_errors.o intl/lang_tdb.o \
lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \
lib/module.o lib/events.o lib/ldap_escape.o @CHARSET_STATIC@ \
- lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o @SOCKWRAP@ \
+ lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o \
libads/krb5_errs.o lib/system_smbd.o lib/audit.o
+LIB_OBJ = $(LIB_WITHOUT_PROTO_OBJ) $(LIB_WITH_PROTO_OBJ)
+
LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o
LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ)
@@ -237,6 +268,14 @@ PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o lib/sharesec.o
KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o
+LIBADDNS_OBJ0 = libaddns/dnsrecord.o libaddns/dnsutils.o libaddns/dnssock.o \
+ libaddns/dnsgss.o libaddns/dnsmarshall.o
+LIBADDNS_OBJ = $(LIBADDNS_OBJ0) $(TALLOC_OBJ)
+
+LIBGPO_OBJ0 = libgpo/gpo_ldap.o libgpo/gpo_parse.o libgpo/gpo_util.o \
+ libgpo/gpo_fetch.o libgpo/gpo_filesync.o
+LIBGPO_OBJ = $(LIBGPO_OBJ0)
+
LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
libads/krb5_setpw.o libads/ldap_user.o \
libads/ads_struct.o libads/kerberos_keytab.o \
@@ -244,7 +283,7 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
libads/authdata.o libads/cldap.o
LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \
- libads/ldap_schema.o sam/nss_info.o
+ libads/ldap_schema.o
SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o
@@ -266,13 +305,16 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
$(DOSERR_OBJ) \
$(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
+RPC_CLIENT_OBJ1 = rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o
+
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
- rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
- rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \
- rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \
+ $(RPC_CLIENT_OBJ1) rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \
rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \
- rpc_client/cli_ds.o rpc_client/cli_echo.o \
- rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o
+ rpc_client/cli_ds.o rpc_client/cli_svcctl.o \
+ rpc_client/cli_shutdown.o rpc_client/cli_dfs.o rpc_client/cli_echo.o
+
+LIBMSRPC_GEN_OBJ = librpc/gen_ndr/cli_wkssvc.o \
+ $(LIBNDR_GEN_OBJ) $(LIBNDR_OBJ)
REGOBJS_OBJ = registry/reg_objects.o
@@ -280,7 +322,7 @@ REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_pri
registry/reg_db.o registry/reg_eventlog.o registry/reg_shares.o \
registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o
-RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o
+RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o
RPC_NETLOG_OBJ = rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o
@@ -295,7 +337,7 @@ RPC_LSA_DS_OBJ = rpc_server/srv_lsa_ds.o rpc_server/srv_lsa_ds_nt.o
RPC_SVC_OBJ = rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o
-RPC_WKS_OBJ = rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o
+RPC_WKS_OBJ = librpc/gen_ndr/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o
RPC_SVCCTL_OBJ = rpc_server/srv_svcctl.o rpc_server/srv_svcctl_nt.o \
services/svc_spoolss.o services/svc_rcinit.o services/services_db.o \
@@ -317,19 +359,14 @@ RPC_ECHO_OBJ = rpc_server/srv_echo.o rpc_server/srv_echo_nt.o
RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ)
-# this includes only the low level parse code, not stuff
-# that requires knowledge of security contexts
-RPC_PARSE_OBJ1 = $(RPC_PARSE_OBJ0) rpc_parse/parse_sec.o
-
-RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
- rpc_parse/parse_reg.o rpc_parse/parse_rpc.o \
- rpc_parse/parse_samr.o rpc_parse/parse_srv.o \
- rpc_parse/parse_wks.o rpc_parse/parse_ds.o \
- rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
- rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \
- rpc_parse/parse_svcctl.o \
- rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \
- rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ)
+RPC_PARSE_OBJ = rpc_parse/parse_lsa.o $(RPC_PARSE_OBJ2) \
+ rpc_parse/parse_samr.o \
+ rpc_parse/parse_ds.o rpc_parse/parse_spoolss.o \
+ rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \
+ rpc_parse/parse_ntsvcs.o rpc_parse/parse_svcctl.o $(REGOBJS_OBJ) \
+ rpc_parse/parse_dfs.o \
+ rpc_parse/parse_reg.o rpc_parse/parse_echo.o \
+ rpc_parse/parse_shutdown.o
RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
@@ -348,7 +385,7 @@ CP850_OBJ = modules/CP850.o
CP437_OBJ = modules/CP437.o
CHARSET_MACOSXFS_OBJ = modules/charset_macosxfs.o
-GROUPDB_OBJ = groupdb/mapping.o
+GROUPDB_OBJ = groupdb/mapping.o groupdb/mapping_tdb.o
PROFILE_OBJ = profile/profile.o
PROFILES_OBJ = utils/profiles.o \
@@ -359,8 +396,9 @@ PROFILES_OBJ = utils/profiles.o \
OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o
-NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o smbd/notify_fam.o
+NOTIFY_OBJ = smbd/notify.o smbd/notify_inotify.o smbd/notify_internal.o
+VFS_DEFAULT_OBJ = modules/vfs_default.o
VFS_AUDIT_OBJ = modules/vfs_audit.o
VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
VFS_FULL_AUDIT_OBJ = modules/vfs_full_audit.o
@@ -373,7 +411,19 @@ 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_POSIXACL_OBJ = modules/vfs_posixacl.o
+VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o
+VFS_AIXACL2_OBJ = modules/vfs_aixacl2.o modules/vfs_aixacl_util.o modules/nfs4_acls.o
+VFS_SOLARISACL_OBJ = modules/vfs_solarisacl.o
+VFS_HPUXACL_OBJ = modules/vfs_hpuxacl.o
+VFS_IRIXACL_OBJ = modules/vfs_irixacl.o
+VFS_TRU64ACL_OBJ = modules/vfs_tru64acl.o
VFS_CATIA_OBJ = modules/vfs_catia.o
+VFS_CACHEPRIME_OBJ = modules/vfs_cacheprime.o
+VFS_PREALLOC_OBJ = modules/vfs_prealloc.o
+VFS_COMMIT_OBJ = modules/vfs_commit.o
+VFS_GPFS_OBJ = modules/vfs_gpfs.o modules/gpfs.o modules/nfs4_acls.o
+VFS_NOTIFY_FAM_OBJ = modules/vfs_notify_fam.o
PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
@@ -408,7 +458,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \
- smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
+ smbd/vfs.o smbd/statcache.o \
smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \
smbd/process.o smbd/service.o smbd/error.o \
printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
@@ -423,7 +473,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
$(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \
$(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
- $(LIBMSRPC_OBJ) \
+ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \
$(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
$(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
$(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
@@ -431,7 +481,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \
printing/print_cups.o printing/print_generic.o \
printing/lpq_parse.o printing/load.o \
- printing/print_iprint.o
+ printing/print_iprint.o printing/print_test.o
PRINTBASE_OBJ = printing/notify.o printing/printing_db.o
PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o $(PRINTBASE_OBJ)
@@ -459,18 +509,14 @@ SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \
$(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \
$(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \
- $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) \
+ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBMSRPC_OBJ) \
$(PASSCHANGE_OBJ)
-SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
- $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) \
- $(DOSERR_OBJ) $(SECRETS_OBJ)
-
-STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
+STATUS_OBJ = utils/status.o utils/status_profile.o \
+ $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
$(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) \
$(DOSERR_OBJ)
-
SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
@@ -480,61 +526,53 @@ SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \
$(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
- rpc_client/cli_srvsvc.o rpc_parse/parse_srv.o \
- rpc_client/cli_pipe.o rpc_parse/parse_rpc.o \
- rpc_client/cli_netlogon.o rpc_parse/parse_net.o
+ rpc_client/cli_pipe.o $(RPC_PARSE_OBJ2) \
+ $(RPC_CLIENT_OBJ1) \
+ $(LIBMSRPC_GEN_OBJ)
TESTPARM_OBJ = utils/testparm.o \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
$(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
-SMBPASSWD_OBJ = utils/smbpasswd.o utils/passwd_util.o $(PASSCHANGE_OBJ) \
+PASSWD_UTIL_OBJ = utils/passwd_util.o
+
+SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSWD_UTIL_OBJ) $(PASSCHANGE_OBJ) \
$(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
$(GROUPDB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
- $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ)
+ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBMSRPC_OBJ)
-PDBEDIT_OBJ = utils/pdbedit.o utils/passwd_util.o $(PARAM_OBJ) $(PASSDB_OBJ) \
+PDBEDIT_OBJ = utils/pdbedit.o $(PASSWD_UTIL_OBJ) $(PARAM_OBJ) $(PASSDB_OBJ) \
$(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) \
$(SECRETS_OBJ) $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o \
- $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
+ $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) libsmb/errormap.o
SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ)
+DISPLAY_SEC_OBJ= lib/display_sec.o
+
RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \
rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \
- rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \
+ rpcclient/cmd_dfs.o \
rpcclient/cmd_ds.o rpcclient/cmd_echo.o \
rpcclient/cmd_shutdown.o rpcclient/cmd_test.o \
- lib/display_sec.o
+ $(DISPLAY_SEC_OBJ)
RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \
- $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \
+ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBMSRPC_OBJ) \
$(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \
$(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
$(SMBLDAP_OBJ) $(DCUTIL_OBJ)
PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
- lib/replace1.o $(SNPRINTF_OBJ) @BUILD_INIPARSER@
-
-SMBW_OBJ1 = smbwrapper/smbw.o \
- smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \
- smbwrapper/realcalls.o smbwrapper/shared.o \
- smbwrapper/smbw_cache.o
-
-SMBW_OBJ = $(SMBW_OBJ1) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
- $(LIB_NONSMBD_OBJ)
-
-SMBWRAPPER_OBJ1 = smbwrapper/wrapped.o
-
-SMBWRAPPER_OBJ = $(SMBW_OBJ) $(SMBWRAPPER_OBJ1)
+ $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @BUILD_INIPARSER@
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) \
+ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) \
$(SECRETS_OBJ) $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ)
CAC_OBJ = $(LIBSMBCLIENT_OBJ) \
@@ -542,7 +580,7 @@ CAC_OBJ = $(LIBSMBCLIENT_OBJ) \
libmsrpc/cac_lsarpc.o libmsrpc/cac_winreg.o libmsrpc/cac_samr.o \
libmsrpc/cac_svcctl.o
-LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
+LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o $(TDB_BASE_OBJ)
# This shared library is intended for linking with unit test programs
# to test Samba internals. It's called libbigballofmud.so to
@@ -551,23 +589,22 @@ LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
LIBBIGBALLOFMUD_MAJOR = 0
LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) \
- $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
+ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
$(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ)
-LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.@PICSUFFIX@)
-
-CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_srvsvc.o \
- rpc_parse/parse_srv.o rpc_client/cli_pipe.o rpc_parse/parse_rpc.o \
- rpc_client/cli_netlogon.o rpc_parse/parse_net.o
+CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_pipe.o \
+ $(RPC_CLIENT_OBJ1) \
+ $(RPC_PARSE_OBJ2)
CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
- $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
+ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(LIBMSRPC_GEN_OBJ) \
$(READLINE_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
- lib/display_sec.o
+ $(DISPLAY_SEC_OBJ)
TOOL_OBJ = client/smbctool.o client/clitar.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
- $(READLINE_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ)
+ $(READLINE_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
+ $(DISPLAY_SEC_OBJ)
NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_domain.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
@@ -577,16 +614,16 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_domain.o utils/net_help.o \
utils/net_rpc_service.o utils/net_rpc_registry.o utils/net_usershare.o \
utils/netlookup.o utils/net_sam.o utils/net_rpc_shell.o \
utils/net_util.o utils/net_rpc_sh_acct.o utils/net_rpc_audit.o \
- utils/passwd_util.o
+ $(PASSWD_UTIL_OBJ) utils/net_dns.o utils/net_ads_gpo.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) \
+ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(LIBADDNS_OBJ0) \
+ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \
$(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
$(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \
$(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ) $(READLINE_OBJ) \
- lib/display_sec.o
+ $(LIBGPO_OBJ) $(INIPARSER_OBJ) $(DISPLAY_SEC_OBJ)
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
@@ -594,9 +631,9 @@ CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
MOUNT_OBJ = client/smbmount.o \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
-MNT_OBJ = client/smbmnt.o lib/replace.o lib/timegm.o $(VERSION_OBJ) $(SNPRINTF_OBJ) @SOCKWRAP@
+MNT_OBJ = client/smbmnt.o $(VERSION_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ)
-UMOUNT_OBJ = client/smbumount.o @SOCKWRAP@
+UMOUNT_OBJ = client/smbumount.o $(SOCKET_WRAPPER_OBJ)
CIFS_MOUNT_OBJ = client/mount.cifs.o
@@ -623,6 +660,11 @@ LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \
NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
+PDBTEST_OBJ = torture/pdbtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+ $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+ $(SMBLDAP_OBJ) $(POPT_LIB_OBJ)
+
+
VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
@@ -634,13 +676,13 @@ LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \
- $(PASSDB_OBJ) $(GROUPDB_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \
+ $(PASSDB_OBJ) $(GROUPDB_OBJ) $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_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) \
- $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
+ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
$(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ)
EVTLOGADM_OBJ0 = utils/eventlogadm.o
@@ -651,14 +693,22 @@ EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ)
registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \
registry/reg_db.o
-TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
+SHARESEC_OBJ0 = utils/sharesec.o
+SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \
+ $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
+ $(POPT_LIB_OBJ) $(SECRETS_OBJ)
+
+TALLOCTORT_OBJ = lib/talloc/testsuite.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ) $(SECRETS_OBJ)
+REPLACETORT_OBJ = lib/replace/test/testsuite.o lib/replace/test/os2_delete.o \
+ $(LIBREPLACE_OBJ)
+
RPCTORTURE_OBJ = torture/rpctorture.o \
rpcclient/display.o \
rpcclient/cmd_lsarpc.o \
- rpcclient/cmd_wkssvc.o \
rpcclient/cmd_samr.o \
+ rpcclient/cmd_wkssvc.o \
rpcclient/cmd_srvsvc.o \
rpcclient/cmd_netlogon.o \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
@@ -669,10 +719,11 @@ DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o
SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ)
-PROTO_OBJ = $(SMBD_OBJ_MAIN) \
- $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
+PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) $(LIBNDR_GEN_OBJ) \
+ $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(LIBSMB_OBJ) \
$(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
- $(LIBMSRPC_OBJ) @SMBWRAP_OBJS@ \
+ $(LIBMSRPC_OBJ) \
+ $(LIB_WITH_PROTO_OBJ) \
$(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) $(KRBCLIENT_OBJ) \
$(AUTH_OBJ) $(PARAM_OBJ) $(LOCKING_OBJ) $(SECRETS_OBJ) \
$(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \
@@ -682,19 +733,12 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
$(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \
$(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
$(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \
- $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) \
- $(RPC_NTSVCS_OBJ) utils/passwd_util.o
+ $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) $(RPC_UNIXINFO_OBJ) \
+ $(RPC_NTSVCS_OBJ) $(RPC_INITSHUTDOWN_OBJ) utils/passwd_util.o \
+ $(LIBGPO_OBJ) $(NSS_INFO_OBJ)
WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \
- $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ)
-
-WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.@PICSUFFIX@)
-
-PICOBJS = $(SMBWRAPPER_OBJ:.o=.@PICSUFFIX@)
-LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@)
-LIBSMBSHAREMODES_PICOBJS = $(LIBSMBSHAREMODES_OBJ:.o=.@PICSUFFIX@)
-CAC_PICOBJS = $(CAC_OBJ:.o=.@PICSUFFIX@)
-
+ $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
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 \
@@ -702,9 +746,11 @@ PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
$(SECRETS_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ) \
$(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
-PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.@PICSUFFIX@)
+IDMAP_OBJ = nsswitch/idmap.o nsswitch/idmap_cache.o nsswitch/idmap_util.o @IDMAP_STATIC@
+
+NSS_INFO_OBJ = nsswitch/nss_info.o @NSS_INFO_STATIC@
-IDMAP_OBJ = sam/idmap.o sam/idmap_util.o @IDMAP_STATIC@
+IDMAP_NSS_OBJ = sam/idmap_nss.o
WINBINDD_OBJ1 = \
nsswitch/winbindd.o \
@@ -724,36 +770,38 @@ WINBINDD_OBJ1 = \
nsswitch/winbindd_dual.o \
nsswitch/winbindd_async.o \
nsswitch/winbindd_creds.o \
- nsswitch/winbindd_cred_cache.o
+ nsswitch/winbindd_cred_cache.o \
+ nsswitch/winbindd_ccache_access.o
WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
- $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
+ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_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) $(NSS_INFO_OBJ) \
$(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \
$(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(SECRETS_OBJ) $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
-WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) lib/replace1.o @WINBIND_NSS_EXTRA_OBJS@
+WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @WINBIND_NSS_EXTRA_OBJS@
-WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.@PICSUFFIX@) lib/snprintf.@PICSUFFIX@
-
-POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
+POPT_OBJ=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
INIPARSER_OBJ = iniparser/src/iniparser.o iniparser/src/dictionary.o \
iniparser/src/strlib.o
-TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(SNPRINTF_OBJ) $(TDBBASE_OBJ)
+TDBBACKUP_OBJ = tdb/tools/tdbbackup.o tdb/common/tdbback.o $(LIBREPLACE_OBJ) \
+ $(TDBBASE_OBJ) $(SOCKET_WRAPPER_OBJ)
-TDBTOOL_OBJ = tdb/tdbtool.o $(TDBBASE_OBJ) $(SNPRINTF_OBJ)
+TDBTOOL_OBJ = tdb/tools/tdbtool.o $(TDBBASE_OBJ) $(LIBREPLACE_OBJ) \
+ $(SOCKET_WRAPPER_OBJ)
-TDBDUMP_OBJ = tdb/tdbdump.o $(TDBBASE_OBJ) $(SNPRINTF_OBJ)
+TDBDUMP_OBJ = tdb/tools/tdbdump.o $(TDBBASE_OBJ) $(LIBREPLACE_OBJ) \
+ $(SOCKET_WRAPPER_OBJ)
NTLM_AUTH_OBJ1 = utils/ntlm_auth.o utils/ntlm_auth_diagnostics.o
@@ -761,7 +809,8 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
- $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ)
+ $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ) \
+ $(LDB_OBJ) libsmb/errormap.o
######################################################################
# now the rules...
@@ -775,8 +824,6 @@ pam_smbpass : SHOWFLAGS proto_exists bin/pam_smbpass.@SHLIBEXT@
pam_winbind : SHOWFLAGS proto_exists bin/pam_winbind.@SHLIBEXT@
-smbwrapper : SHOWFLAGS @SMBWRAPPER@
-
torture : SHOWFLAGS $(TORTURE_PROGS)
smbtorture : SHOWFLAGS bin/smbtorture@EXEEXT@
@@ -803,8 +850,12 @@ smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@
eventlogadm: SHOWFLAGS bin/eventlogadm@EXEEXT@
+sharesec: SHOWFLAGS bin/sharesec@EXEEXT@
+
talloctort : SHOWFLAGS bin/talloctort@EXEEXT@
+replacetort : SHOWFLAGS bin/replacetort@EXEEXT@
+
timelimit : SHOWFLAGS bin/timelimit@EXEEXT@
nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ @WINBIND_NSS@ \
@@ -816,19 +867,22 @@ modules: SHOWFLAGS proto_exists $(MODULES)
cac: SHOWFLAGS $(LIBMSRPC)
-everything: all libsmbclient debug2html smbfilter talloctort modules torture \
+
+everything: all libsmbclient debug2html smbfilter talloctort replacetort modules torture \
$(EVERYTHING_PROGS)
.SUFFIXES:
-.SUFFIXES: .c .o .@PICSUFFIX@ .lo
+.SUFFIXES: .c .o .lo
SHOWFLAGS:
- @echo "Using FLAGS = $(FLAGS)"
- @echo " LIBS = $(LIBS)"
- @echo " LDSHFLAGS = $(LDSHFLAGS)"
- @echo " LDFLAGS = $(LDFLAGS)"
- @echo " PIE_CFLAGS = @PIE_CFLAGS@"
- @echo " PIE_LDFLAGS = @PIE_LDFLAGS@"
+ @echo "Using FLAGS = $(FLAGS)"
+ @echo " PICFLAG = $(PICFLAG)"
+ @echo " LIBS = $(LIBS)"
+ @echo " LDFLAGS = $(LDFLAGS)"
+ @echo " DYNEXP = $(DYNEXP)"
+ @echo " LDSHFLAGS = $(LDSHFLAGS)"
+ @echo " SHLIBEXT = @SHLIBEXT@"
+ @echo " SONAMEFLAG = @SONAMEFLAG@"
MAKEDIR = || exec false; \
if test -d "$$dir"; then :; else \
@@ -843,17 +897,20 @@ MAKEDIR = || exec false; \
dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
@if test -n "$(CC_CHECKER)"; then \
echo "Checking $*.c with '$(CC_CHECKER)'";\
- $(CC_CHECKER) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $< -o $@;\
+ $(CC_CHECKER) -I. -I$(srcdir) $(FLAGS) $(PICFLAG) -c $< -o $@;\
fi
@echo Compiling $*.c
- @$(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $< -o $@
+ @$(CC) -I. -I$(srcdir) $(FLAGS) $(PICFLAG) -c $< -o $@ && exit 0;\
+ echo "The following command failed:" 1>&2;\
+ echo "$(CC) -I. -I$(srcdir) $(FLAGS) $(PICFLAG) -c $< -o $@" 1>&2;\
+ $(CC) -I. -I$(srcdir) $(FLAGS) $(PICFLAG) -c $< -o $@ >/dev/null 2>&1
@BROKEN_CC@ -mv `echo $@ | sed 's%^.*/%%g'` $@
# this adds support for precompiled headers. To use it, install a snapshot
# of gcc-3.4 and run 'make pch' before you do the main build.
pch: proto_exists
rm -f $(builddir)/include/includes.h.gch
- $(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $(srcdir)/include/includes.h -o $(builddir)/include/includes.h.gch
+ $(CC) -I. -I$(srcdir) $(FLAGS) $(PICFLAG) -c $(srcdir)/include/includes.h -o $(builddir)/include/includes.h.gch
# These dependencies are only approximately correct: we want to make
# sure Samba's paths are updated if ./configure is re-run. Really it
@@ -863,56 +920,27 @@ pch: proto_exists
dynconfig.o: dynconfig.c Makefile
@echo Compiling $*.c
- @$(CC) $(FLAGS) $(PATH_FLAGS) @PIE_CFLAGS@ -c $(srcdir)/dynconfig.c -o $@
-
-dynconfig.@PICSUFFIX@: dynconfig.c Makefile
- @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
- dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
- @echo Compiling $*.c with @PICFLAGS@
- @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $(srcdir)/dynconfig.c -o $@
-@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
+ @$(CC) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c $(srcdir)/dynconfig.c -o $@ && exit 0;\
+ echo "The following command failed:" 1>&2;\
+ echo "$(CC) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c $(srcdir)/dynconfig.c -o $@" 1>&2;\
+ $(CC) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c $(srcdir)/dynconfig.c -o $@ >/dev/null 2>&1
lib/pidfile.o: lib/pidfile.c
@echo Compiling $*.c
- @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PIE_CFLAGS@ -c $(srcdir)/lib/pidfile.c -o $@
-
-lib/pidfile.@PICSUFFIX@: lib/pidfile.c
- @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
- dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
- @echo Compiling $*.c with @PICFLAGS@
- @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $(srcdir)/lib/pidfile.c -o $@
-@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
+ @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c $(srcdir)/lib/pidfile.c -o $@
lib/version.o: lib/version.c include/version.h
@echo Compiling $*.c
- @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PIE_CFLAGS@ -c $(srcdir)/lib/version.c -o $@
-
-lib/version.@PICSUFFIX@: lib/version.c include/version.h
- @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
- dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
- @echo Compiling $*.c with @PICFLAGS@
- @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $(srcdir)/lib/version.c -o $@
-@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
+ @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c $(srcdir)/lib/version.c -o $@
smbd/build_options.o: smbd/build_options.c Makefile include/config.h include/build_env.h include/proto.h
@echo Compiling $*.c
- @$(CC) $(FLAGS) $(PATH_FLAGS) @PIE_CFLAGS@ -c smbd/build_options.c -o $@
+ @$(CC) $(FLAGS) $(PATH_FLAGS) $(PICFLAG) -c smbd/build_options.c -o $@
smbd/build_options.c: include/config.h.in script/mkbuildoptions.awk
@echo Generating $@
@dir=smbd $(MAKEDIR) && $(AWK) -f $(srcdir)/script/mkbuildoptions.awk > $(builddir)/smbd/build_options.c < $(srcdir)/include/config.h.in
-.c.@PICSUFFIX@:
- @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
- dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
- @if test -n "$(CC_CHECKER)"; then \
- echo "Checking $*.c with '$(CC_CHECKER)' and @PICFLAGS@";\
- $(CC_CHECKER) -I. -I$(srcdir) $(FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@;\
- fi
- @echo Compiling $*.c with @PICFLAGS@
- @$(CC) -I. -I$(srcdir) $(FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@
-@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
-
bin/.dummy:
@if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \
dir=bin $(MAKEDIR); fi
@@ -920,218 +948,228 @@ bin/.dummy:
bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
+ @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
$(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \
$(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @SMBD_LIBS@
bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \
+ @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \
$(AUTH_LIBS) $(LIBS) $(PASSDB_LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/rpcclient@EXEEXT@: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \
$(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \
$(KRB5LIBS) $(LDAP_LIBS)
bin/smbclient@EXEEXT@: $(CLIENT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/smbctool@EXEEXT@: $(TOOL_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(TOOL_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) -Lbin -lsmbclient
+ @$(CC) $(FLAGS) -o $@ $(TOOL_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) -Lbin -lsmbclient
-bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy
+bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ @BUILD_INIPARSER@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS)
+ @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(UUID_LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS) $(NSCD_LIBS) @INIPARSERLIBS@
bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
bin/smbspool@EXEEXT@: $(CUPS_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmount@EXEEXT@: $(MOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmnt@EXEEXT@: $(MNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MNT_OBJ) $(DYNEXP) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(MNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/smbumount@EXEEXT@: $(UMOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/mount.cifs@EXEEXT@: $(CIFS_MOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(CIFS_MOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/umount.cifs@EXEEXT@: $(CIFS_UMOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(CIFS_UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/testparm@EXEEXT@: $(TESTPARM_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
bin/smbstatus@EXEEXT@: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) \
@POPTLIBS@
bin/smbcontrol@EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) -DUSING_SMBCONTROL $(FLAGS) @PIE_LDFLAGS@ -o $@ \
+ @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ \
$(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \
- $(LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@
+ $(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@
bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \
+ @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \
$(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS)
bin/smbget@EXEEXT@: $(SMBGET_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS)
bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/nmblookup@EXEEXT@: $(NMBLOOKUP_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(LDAP_LIBS)
bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) \
+ $(DYNEXP) $(LIBS) $(LDAP_LIBS)
+
+bin/replacetort@EXEEXT@: $(REPLACETORT_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(REPLACETORT_OBJ) $(LDFLAGS) \
+ $(DYNEXP) $(LIBS)
bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \
+ @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \
$(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS)
bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \
+ @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ \
$(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS)
bin/eventlogadm@EXEEXT@: $(EVTLOGADM_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
+
+bin/sharesec@EXEEXT@: $(SHARESEC_OBJ) @BUILD_POPT@ bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+
+bin/pdbtest@EXEEXT@: $(PDBTEST_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(PDBTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@
bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@ $(NSCD_LIBS)
bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@
bin/log2pcap@EXEEXT@: $(LOG2PCAP_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS)
bin/locktest2@EXEEXT@: $(LOCKTEST2_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
-
-bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy
- @echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
-bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy
- @echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBSH_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
+bin/libaddns.@SHLIBEXT@: $(LIBADDNS_OBJ)
+ @echo Linking libaddns shared library $@
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBADDNS_OBJ) $(LDFLAGS) $(LIBS) \
+ $(KRB5LIBS) $(UUID_LIBS)\
+ @SONAMEFLAG@`basename $@`.$(LIBADDNS_MAJOR)
-bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy
- @echo Linking shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(PICOBJS) $(LIBS) \
- $(KRB5LIBS) $(LDAP_LIBS) \
- @SONAMEFLAG@`basename $@`
+bin/libaddns.a: $(LIBADDNS_OBJ)
+ @echo Linking libaddns non-shared library $@
+ @-$(AR) -rc $@ $(LIBADDNS_OBJ)
-bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS)
+bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_OBJ)
@echo Linking libsmbclient shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \
- $(KRB5LIBS) $(LDAP_LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_OBJ) $(LDFLAGS) $(LIBS) \
+ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR)
-bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS)
+bin/libsmbclient.a: $(LIBSMBCLIENT_OBJ)
@echo Linking libsmbclient non-shared library $@
- @-$(AR) -rc $@ $(LIBSMBCLIENT_PICOBJS)
+ @-$(AR) -rc $@ $(LIBSMBCLIENT_OBJ)
-bin/libsmbsharemodes.@SHLIBEXT@: $(LIBSMBSHAREMODES_PICOBJS)
+bin/libsmbsharemodes.@SHLIBEXT@: $(LIBSMBSHAREMODES_OBJ)
@echo Linking libsmbsharemodes shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBSHAREMODES_PICOBJS) $(LDFLAGS) $(LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBSHAREMODES_OBJ) $(LDFLAGS) $(LIBS) \
$(KRB5LIBS) $(LDAP_LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBSMBSHAREMODES_MAJOR)
-bin/libsmbsharemodes.a: $(LIBSMBSHAREMODES_PICOBJS)
+bin/libsmbsharemodes.a: $(LIBSMBSHAREMODES_OBJ)
@echo Linking libsmbsharemodes non-shared library $@
- @-$(AR) -rc $@ $(LIBSMBSHAREMODES_PICOBJS)
+ @-$(AR) -rc $@ $(LIBSMBSHAREMODES_OBJ)
-bin/libmsrpc.@SHLIBEXT@: $(CAC_PICOBJS)
+bin/libmsrpc.@SHLIBEXT@: $(CAC_OBJ)
@echo Linking libmsrpc shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(CAC_PICOBJS) $(LDFLAGS) $(LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(CAC_OBJ) $(LDFLAGS) $(LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBMSRPC_MAJOR)
-bin/libmsrpc.a: $(CAC_PICOBJS)
+bin/libmsrpc.a: $(CAC_OBJ)
@echo Linking libmsrpc non-shared library $@
- @-$(AR) -rc $@ $(CAC_PICOBJS)
+ @-$(AR) -rc $@ $(CAC_OBJ)
# This is probably wrong for anything other than the GNU linker.
-bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS)
+bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_OBJ)
@echo Linking bigballofmud shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_PICOBJS) $(LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_OBJ) $(LIBS) \
$(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR)
ln -snf libbigballofmud.so bin/libbigballofmud.so.0
@@ -1144,6 +1182,7 @@ bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS)
libsmbclient: $(LIBSMBCLIENT)
libsmbsharemodes: $(LIBSMBSHAREMODES)
libmsrpc: $(LIBMSRPC)
+libaddns: $(LIBADDNS)
bin/librpc_lsarpc.@SHLIBEXT@: $(RPC_LSA_OBJ)
@echo "Linking $@"
@@ -1155,6 +1194,11 @@ bin/librpc_samr.@SHLIBEXT@: $(RPC_SAMR_OBJ)
@$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SAMR_OBJ) -lc \
@SONAMEFLAG@`basename $@`
+bin/librpc_unixinfo.@SHLIBEXT@: $(RPC_UNIXINFO_OBJ)
+ @echo "Linking $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_UNIXINFO_OBJ) -lc \
+ @SONAMEFLAG@`basename $@`
+
bin/librpc_srvsvc.@SHLIBEXT@: $(RPC_SVC_OBJ)
@echo "Linking $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVC_OBJ) -lc \
@@ -1180,11 +1224,16 @@ bin/librpc_NETLOGON.@SHLIBEXT@: $(RPC_NETLOG_OBJ)
@$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_NETLOG_OBJ) -lc \
@SONAMEFLAG@`basename $@`
-bin/librpc_winreg.@SHLIBEXT@: $(RPC_REG_OBJ)
+bin/librpc_reg.@SHLIBEXT@: $(RPC_REG_OBJ)
@echo "Linking $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_REG_OBJ) -lc \
@SONAMEFLAG@`basename $@`
+bin/librpc_initshutdown.@SHLIBEXT@: $(RPC_INITSHUTDOWN_OBJ)
+ @echo "Linking $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_INITSHUTDOWN_OBJ) -lc \
+ @SONAMEFLAG@`basename $@`
+
bin/librpc_lsa_ds.@SHLIBEXT@: $(RPC_LSA_DS_OBJ)
@echo "Linking $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_LSA_DS_OBJ) -lc \
@@ -1212,154 +1261,154 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ)
bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@echo "Linking $@"
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
@POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
-# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
-# libraries. Add to the appropriate PICOBJ variable instead.
-
-@WINBIND_NSS@: $(WINBIND_NSS_PICOBJS)
+@WINBIND_NSS@: $(WINBIND_NSS_OBJ)
@echo "Linking $@"
- @$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_PICOBJS) \
+ @$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_OBJ) \
@WINBIND_NSS_EXTRA_LIBS@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
-@WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_PICOBJS)
+@WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_OBJ)
@echo "Linking $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) \
- $(LDAP_LIBS) $(KRB5LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_OBJ) \
+ $(LDAP_LIBS) $(KRB5LIBS) $(LIBS) \
@SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
-bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ:.o=.@PICSUFFIX@) bin/.dummy
+bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy
@echo "Linking shared library $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) \
@SONAMEFLAG@`basename $@` -lpam @INIPARSERLIBS@
-bin/builtin.@SHLIBEXT@: $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@)
+bin/builtin.@SHLIBEXT@: $(AUTH_BUILTIN_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_BUILTIN_OBJ) @SONAMEFLAG@`basename $@`
-bin/domain.@SHLIBEXT@: $(AUTH_DOMAIN_OBJ:.o=.@PICSUFFIX@)
+bin/domain.@SHLIBEXT@: $(AUTH_DOMAIN_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_DOMAIN_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_DOMAIN_OBJ) @SONAMEFLAG@`basename $@`
-bin/script.@SHLIBEXT@: $(AUTH_SCRIPT_OBJ:.o=.@PICSUFFIX@)
+bin/script.@SHLIBEXT@: $(AUTH_SCRIPT_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SCRIPT_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SCRIPT_OBJ) @SONAMEFLAG@`basename $@`
-bin/smbserver.@SHLIBEXT@: $(AUTH_SERVER_OBJ:.o=.@PICSUFFIX@)
+bin/smbserver.@SHLIBEXT@: $(AUTH_SERVER_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SERVER_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SERVER_OBJ) @SONAMEFLAG@`basename $@`
-bin/winbind.@SHLIBEXT@: $(AUTH_WINBIND_OBJ:.o=.@PICSUFFIX@)
+bin/winbind.@SHLIBEXT@: $(AUTH_WINBIND_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_WINBIND_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_WINBIND_OBJ) @SONAMEFLAG@`basename $@`
-bin/unix.@SHLIBEXT@: $(AUTH_UNIX_OBJ:.o=.@PICSUFFIX@)
+bin/unix.@SHLIBEXT@: $(AUTH_UNIX_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_UNIX_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_UNIX_OBJ) @SONAMEFLAG@`basename $@`
-bin/sam.@SHLIBEXT@: $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@)
+bin/sam.@SHLIBEXT@: $(AUTH_SAM_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SAM_OBJ) @SONAMEFLAG@`basename $@`
-bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.@PICSUFFIX@
+bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.o
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.@PICSUFFIX@ \
+ @$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.o \
@SONAMEFLAG@`basename $@`
-bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.@PICSUFFIX@
+bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.o
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_tdb.@PICSUFFIX@ \
+ @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_tdb.o \
@SONAMEFLAG@`basename $@`
-bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.@PICSUFFIX@
+bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.o
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.@PICSUFFIX@ \
+ @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.o \
@SONAMEFLAG@`basename $@`
-bin/rid.@SHLIBEXT@: sam/idmap_rid.@PICSUFFIX@
+bin/rid.@SHLIBEXT@: nsswitch/idmap_rid.o
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ sam/idmap_rid.@PICSUFFIX@ \
+ @$(SHLD) $(LDSHFLAGS) -o $@ nsswitch/idmap_rid.o \
@SONAMEFLAG@`basename $@`
-bin/ad.@SHLIBEXT@: sam/idmap_ad.@PICSUFFIX@
+bin/ad.@SHLIBEXT@: nsswitch/idmap_ad.o
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ sam/idmap_ad.@PICSUFFIX@ \
+ @$(SHLD) $(LDSHFLAGS) -o $@ nsswitch/idmap_ad.o \
@SONAMEFLAG@`basename $@`
-bin/weird.@SHLIBEXT@: $(DEVEL_HELP_WEIRD_OBJ:.o=.@PICSUFFIX@)
+bin/weird.@SHLIBEXT@: $(DEVEL_HELP_WEIRD_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/CP850.@SHLIBEXT@: $(CP850_OBJ:.o=.@PICSUFFIX@)
+bin/CP850.@SHLIBEXT@: $(CP850_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(CP850_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(CP850_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/CP437.@SHLIBEXT@: $(CP437_OBJ:.o=.@PICSUFFIX@)
+bin/CP437.@SHLIBEXT@: $(CP437_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(CP437_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(CP437_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@)
+bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ) \
-framework CoreFoundation @SONAMEFLAG@`basename $@`
-bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@)
+# NOTE, there is no build rule for a dynamic default VFS module because
+# this one MUST MUST MUST be built statically.
+
+bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ:.o=.@PICSUFFIX@)
+bin/extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXTD_AUDIT_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXTD_AUDIT_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/full_audit.@SHLIBEXT@: $(VFS_FULL_AUDIT_OBJ:.o=.@PICSUFFIX@)
+bin/full_audit.@SHLIBEXT@: $(VFS_FULL_AUDIT_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FULL_AUDIT_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FULL_AUDIT_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ:.o=.@PICSUFFIX@)
+bin/recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ:.o=.@PICSUFFIX@)
+bin/netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ:.o=.@PICSUFFIX@)
+bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ:.o=.@PICSUFFIX@)
+bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@)
+bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/shadow_copy.@SHLIBEXT@: $(VFS_SHADOW_COPY_OBJ:.o=.@PICSUFFIX@)
+bin/shadow_copy.@SHLIBEXT@: $(VFS_SHADOW_COPY_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SHADOW_COPY_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SHADOW_COPY_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.@PICSUFFIX@)
+bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ) \
@SONAMEFLAG@`basename $@`
-bin/expand_msdfs.@SHLIBEXT@: $(VFS_EXPAND_MSDFS_OBJ:.o=.@PICSUFFIX@)
+bin/expand_msdfs.@SHLIBEXT@: $(VFS_EXPAND_MSDFS_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXPAND_MSDFS_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXPAND_MSDFS_OBJ) \
@SONAMEFLAG@`basename $@`
bin/afsacl.@SHLIBEXT@: $(VFS_AFSACL_OBJ:.o=.po)
@@ -1367,64 +1416,127 @@ 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@)
+bin/posixacl.@SHLIBEXT@: $(VFS_POSIXACL_OBJ)
@echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_POSIXACL_OBJ) \
@SONAMEFLAG@`basename $@`
+bin/aixacl.@SHLIBEXT@: $(VFS_AIXACL_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AIXACL_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/aixacl2.@SHLIBEXT@: $(VFS_AIXACL2_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AIXACL2_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/solarisacl.@SHLIBEXT@: $(VFS_SOLARISACL_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SOLARISACL_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/irixacl.@SHLIBEXT@: $(VFS_IRIXACL_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_IRIXACL_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/hpuxacl.@SHLIBEXT@: $(VFS_HPUXACL_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_HPUXACL_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/tru64acl.@SHLIBEXT@: $(VFS_TRU64ACL_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_TRU64ACL_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/catia.@SHLIBEXT@: $(VFS_CATIA_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/cacheprime.@SHLIBEXT@: $(VFS_CACHEPRIME_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CACHEPRIME_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/prealloc.@SHLIBEXT@: $(VFS_PREALLOC_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_PREALLOC_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/commit.@SHLIBEXT@: $(VFS_COMMIT_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_COMMIT_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/gpfs.@SHLIBEXT@: $(VFS_GPFS_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_GPFS_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+bin/notify_fam.@SHLIBEXT@: $(VFS_NOTIFY_FAM_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NOTIFY_FAM_OBJ) \
+ @SONAMEFLAG@`basename $@`
+
+#########################################################
+## IdMap NSS plugins
+
+## None here right now
+#########################################################
bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
@BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBS) \
@POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS)
-bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
+bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_OBJ)
@echo "Linking shared library $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS)
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_OBJ) -lpam $(DYNEXP) $(LIBS) $(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS)
bin/tdbbackup@EXEEXT@: $(TDBBACKUP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBBACKUP_OBJ) @SOCKWRAP@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBBACKUP_OBJ)
bin/tdbtool@EXEEXT@: $(TDBTOOL_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBTOOL_OBJ) @SOCKWRAP@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBTOOL_OBJ)
bin/tdbdump@EXEEXT@: $(TDBDUMP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBDUMP_OBJ) @SOCKWRAP@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBDUMP_OBJ)
bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
bin/t_strstr@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
bin/t_strappend@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud
bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud
bin/t_doschar@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_doschar.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
-
-bin/t_snprintf@EXEEXT@: lib/snprintf.c
- $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) -DTEST_SNPRINTF lib/snprintf.c -lm
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
bin/timelimit@EXEEXT@: script/tests/timelimit.o
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) script/tests/timelimit.o
+ @$(CC) $(FLAGS) -o $@ $(DYNEXP) script/tests/timelimit.o
+
+install: installservers installbin @INSTALL_CIFSMOUNT@ installman installscripts installdat installswat installmodules @INSTALL_LIBSMBCLIENT@ @INSTALL_LIBMSRPC@ @INSTALL_PAM_MODULES@ @INSTALL_LIBSMBSHAREMODES@
-install: installservers installbin @INSTALL_CIFSMOUNT@ installman installscripts installdat installswat installmodules @INSTALL_LIBSMBCLIENT@ @INSTALL_LIBMSRPC@ @INSTALL_PAM_MODULES@
install-everything: install installmodules
@@ -1490,6 +1602,16 @@ installlibmsrpc: installdirs libmsrpc
@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) ${prefix}/include
-$(INSTALLCMD) $(srcdir)/include/libmsrpc.h $(DESTDIR)${prefix}/include
+installlibsmbsharemodes: installdirs libsmbsharemodes
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(LIBDIR)
+ -$(INSTALLLIBCMD_SH) bin/libsmbsharemodes.@SHLIBEXT@ $(DESTDIR)$(LIBDIR)
+ -$(INSTALLLIBCMD_A) bin/libsmbsharemodes.a $(DESTDIR)$(LIBDIR)
+
+installlibaddns: installdirs libaddns
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(LIBDIR)
+ -$(INSTALLLIBCMD_SH) bin/libaddns.@SHLIBEXT@ $(DESTDIR)$(LIBDIR)
+ -$(INSTALLLIBCMD_A) bin/libaddns.a $(DESTDIR)$(LIBDIR)
+
installpammodules: $(PAM_MODULES)
@$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(PAMMODULESDIR)
@for module in $(PAM_MODULES); do \
@@ -1500,28 +1622,26 @@ installpammodules: $(PAM_MODULES)
# Python extensions
-PYTHON_OBJS = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \
- $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+PYTHON_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \
+ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ)
-PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.@PICSUFFIX@)
-
-python_ext: $(PYTHON_PICOBJS)
+python_ext: $(PYTHON_OBJ)
@if test -z "$(PYTHON)"; then \
echo Use the option --with-python to configure python; \
exit 1; \
fi
- PYTHON_OBJS="$(PYTHON_PICOBJS)" \
+ PYTHON_OBJS="$(PYTHON_OBJ)" \
PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \
LIBS="$(LDFLAGS) $(LIBS) $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS)" \
$(PYTHON) python/setup.py build
-python_install: $(PYTHON_PICOBJS)
+python_install: $(PYTHON_OBJ)
@if test -z "$(PYTHON)"; then \
echo Use the option --with-python to configure python; \
exit 1; \
fi
- PYTHON_OBJS="$(PYTHON_PICOBJS)" \
+ PYTHON_OBJS="$(PYTHON_OBJ)" \
PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS)" \
LIBS="$(LDFLAGS) $(LIBS)" \
$(PYTHON) python/setup.py install --root=$(DESTDIR)
@@ -1554,7 +1674,7 @@ showlayout:
@echo " swatdir: $(SWATDIR)"
-uninstall: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ uninstallscripts uninstalldat uninstallswat uninstallmodules @UNINSTALL_LIBSMBCLIENT@ @UNINSTALL_LIBMSRPC@ @UNINSTALL_PAM_MODULES@
+uninstall: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ uninstallscripts uninstalldat uninstallswat uninstallmodules @UNINSTALL_LIBSMBCLIENT@ @UNINSTALL_LIBMSRPC@ @UNINSTALL_PAM_MODULES@ @UNINSTALL_LIBSMBSHAREMODES@
uninstallman:
@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
@@ -1588,16 +1708,24 @@ uninstallmsg:
uninstallswat: uninstallmsg
@$(SHELL) $(srcdir)/script/uninstallswat.sh $(DESTDIR) $(SWATDIR) $(srcdir)
-uninstallclientlib: installdirs libsmbclient
+uninstallclientlib:
-$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libsmbclient.@SHLIBEXT@
-$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libsmbclient.a
-rm -f $(DESTDIR)${prefix}/include/libsmbclient.h
-uninstalllibmsrpc: installdirs libmsrpc
+uninstalllibmsrpc:
-$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libmsrpc.@SHLIBEXT@
-$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libmsrpc.a
-rm -f $(DESTDIR)${prefix}/include/libmsrpc.h
+uninstalllibsmbsharemodes:
+ -$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libsmbsharemodes.@SHLIBEXT@
+ -$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libsmbsharemodes.a
+
+uninstalllibaddns:
+ -$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libaddns.@SHLIBEXT@
+ -$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libaddns.a
+
uninstallpammodules:
@for module in $(PAM_MODULES); do \
echo "Removing $(DESTDIR)/$(PAMMODULESDIR)/$${module}.@SHLIBEXT@ "; \
@@ -1605,14 +1733,15 @@ uninstallpammodules:
done
# Toplevel clean files
-TOPFILES=dynconfig.o dynconfig.@PICSUFFIX@
+TOPFILES=dynconfig.o
clean: delheaders python_clean
- -rm -f core */*~ *~ */*.o */*.@PICSUFFIX@ */*.@SHLIBEXT@ \
+ -rm -f core */*~ *~ */*.o */*/*.o */*/*/*.o \
+ */*.@SHLIBEXT@ */*/*.@SHLIBEXT@ */*/*/*.@SHLIBEXT@ \
$(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(ROOT_SBIN_PROGS) \
- $(MODULES) $(TORTURE_PROGS) $(LIBSMBCLIENT) \
+ $(MODULES) $(TORTURE_PROGS) $(LIBSMBCLIENT) $(LIBADDNS) \
$(LIBSMBSHAREMODES) $(EVERYTHING_PROGS) $(LIBMSRPC) \
- .headers.stamp */src/*.o */src/*.@PICSUFFIX@
+ .headers.stamp */src/*.o
-rm -rf t_dir
# Making this target will just make sure that the prototype files
@@ -1625,7 +1754,7 @@ proto_exists: include/proto.h include/build_env.h \
delheaders:
@echo Removing prototype headers
- @rm -f include/proto.h include/build_env.h \
+ @rm -f include/proto.h include/build_env.h \
nsswitch/winbindd_proto.h web/swat_proto.h \
client/client_proto.h utils/net_proto.h \
smbd/build_options.c utils/ntlm_auth_proto.h \
@@ -1667,7 +1796,7 @@ utils/net_proto.h:
utils/passwd_proto.h:
@cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
-h _PASSWD_PROTO_H_ $(builddir)/utils/passwd_proto.h \
- utils/passwd_util.o
+ $(PASSWD_UTIL_OBJ)
utils/ntlm_auth_proto.h:
@cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
@@ -1694,10 +1823,10 @@ proto: headers
.PHONY: headers proto
etags:
- etags `find $(srcdir) -name "*.[ch]" | grep -v /CVS/`
+ etags `find $(srcdir) -name "*.[ch]" | grep -v /.svn/`
ctags:
- ctags `find $(srcdir) -name "*.[ch]" | grep -v /CVS/`
+ ctags `find $(srcdir) -name "*.[ch]" | grep -v /.svn/`
realclean: clean delheaders
-rm -f config.log bin/.dummy script/findsmb script/gen-8bit-gap.sh
@@ -1750,11 +1879,11 @@ test_pam_modules: pam_modules
##
test: all torture timelimit
@echo Running Test suite
- @sh ./script/tests/selftest.sh ${selftest_prefix}/st all "${smbtorture4_path}"
+ @sh $(srcdir)/script/tests/selftest.sh ${selftest_prefix}/st all "${smbtorture4_path}"
valgrindtest: all torture timelimit
@echo Running Test suite with valgrind
@NMBD_VALGRIND="xterm -n smbd -e valgrind -q --db-attach=yes --num-callers=30" \
SMBD_VALGRIND="xterm -n smbd -e valgrind -q --db-attach=yes --num-callers=30" \
VALGRIND="valgrind -q --num-callers=30 --log-file=${selftest_prefix}/st/valgrind.log" \
- ./script/tests/selftest.sh ${selftest_prefix}/st all "${smbtorture4_path}"
+ $(srcdir)/script/tests/selftest.sh ${selftest_prefix}/st all "${smbtorture4_path}"
diff --git a/source/VERSION b/source/VERSION
index 8d8dd8dd474..fc1f872b07a 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -25,7 +25,7 @@
########################################################
SAMBA_VERSION_MAJOR=3
SAMBA_VERSION_MINOR=0
-SAMBA_VERSION_RELEASE=24
+SAMBA_VERSION_RELEASE=25
########################################################
# If a official release has a serious bug #
@@ -47,7 +47,7 @@ SAMBA_VERSION_REVISION=
# 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/aclocal.m4 b/source/aclocal.m4
index af7ed7b4068..d36749a5f50 100644
--- a/source/aclocal.m4
+++ b/source/aclocal.m4
@@ -1,28 +1,3 @@
-dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)]
-dnl if the cache file is inconsistent with the current host,
-dnl target and build system types, execute CMD or print a default
-dnl error message.
-AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
- AC_REQUIRE([AC_CANONICAL_SYSTEM])
- AC_MSG_CHECKING([config.cache system type])
- if { test x"${ac_cv_host_system_type+set}" = x"set" &&
- test x"$ac_cv_host_system_type" != x"$host"; } ||
- { test x"${ac_cv_build_system_type+set}" = x"set" &&
- test x"$ac_cv_build_system_type" != x"$build"; } ||
- { test x"${ac_cv_target_system_type+set}" = x"set" &&
- test x"$ac_cv_target_system_type" != x"$target"; }; then
- AC_MSG_RESULT([different])
- ifelse($#, 1, [$1],
- [AC_MSG_ERROR(["you must remove config.cache and restart configure"])])
- else
- AC_MSG_RESULT([same])
- fi
- ac_cv_host_system_type="$host"
- ac_cv_build_system_type="$build"
- ac_cv_target_system_type="$target"
-])
-
-
dnl test whether dirent has a d_off member
AC_DEFUN(AC_DIRENT_D_OFF,
[AC_CACHE_CHECK([for d_off in dirent], ac_cv_dirent_d_off,
@@ -78,32 +53,6 @@ AC_DEFUN(SMB_SUBSYSTEM,
ifelse([$2], , :, [rm -f $2])
])
-dnl AC_PROG_CC_FLAG(flag)
-AC_DEFUN(AC_PROG_CC_FLAG,
-[AC_CACHE_CHECK(whether ${CC-cc} accepts -$1, ac_cv_prog_cc_$1,
-[echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -$1 -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_$1=yes
-else
- ac_cv_prog_cc_$1=no
-fi
-rm -f conftest*
-])])
-
-dnl see if a declaration exists for a function or variable
-dnl defines HAVE_function_DECL if it exists
-dnl AC_HAVE_DECL(var, includes)
-AC_DEFUN(AC_HAVE_DECL,
-[
- AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[
- AC_TRY_COMPILE([$2],[int i = (int)$1],
- ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)])
- if test x"$ac_cv_have_$1_decl" = x"yes"; then
- AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available])
- fi
-])
-
-
dnl AC_LIBTESTFUNC(lib, function, [actions if found], [actions if not found])
dnl Check for a function in a library, but don't keep adding the same library
dnl to the LIBS variable. Check whether the function is available in the
@@ -112,55 +61,59 @@ dnl adding libraries for symbols that are in libc.
dnl
dnl On success, the default actions ensure that HAVE_FOO is defined. The lib
dnl is always added to $LIBS if it was found to be necessary. The caller
-dnl can use SMB_LIB_REMOVE to strp this if necessary.
+dnl can use SMB_REMOVE_LIB to strp this if necessary.
AC_DEFUN([AC_LIBTESTFUNC],
[
AC_CHECK_FUNCS($2,
[
# $2 was found in libc or existing $LIBS
- ifelse($3, [],
+ m4_ifval([$3],
[
- AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
- [Whether $2 is available])
+ $3
],
[
- $3
+ AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
+ [Whether $2 is available])
])
],
[
# $2 was not found, try adding lib$1
case " $LIBS " in
*\ -l$1\ *)
- ifelse($4, [],
+ m4_ifval([$4],
+ [
+ $4
+ ],
[
# $2 was not found and we already had lib$1
# nothing to do here by default
true
- ],
- [ $4 ])
+ ])
;;
*)
# $2 was not found, try adding lib$1
AC_CHECK_LIB($1, $2,
[
LIBS="-l$1 $LIBS"
- ifelse($3, [],
+ m4_ifval([$3],
[
- AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
- [Whether $2 is available])
+ $3
],
[
- $3
+ AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
+ [Whether $2 is available])
])
],
[
- ifelse($4, [],
+ m4_ifval([$4],
+ [
+ $4
+ ],
[
# $2 was not found in lib$1
# nothing to do here by default
true
- ],
- [ $4 ])
+ ])
])
;;
esac
@@ -303,285 +256,6 @@ else
fi])
])
-# Configure paths for LIBXML2
-# Toshio Kuratomi 2001-04-21
-# Adapted from:
-# Configure paths for GLIB
-# Owen Taylor 97-11-3
-
-dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
-dnl Test for XML, and define XML_CFLAGS and XML_LIBS
-dnl
-AC_DEFUN(AM_PATH_XML2,[
-AC_ARG_WITH(xml-prefix,
- [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)],
- xml_config_prefix="$withval", xml_config_prefix="")
-AC_ARG_WITH(xml-exec-prefix,
- [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)],
- xml_config_exec_prefix="$withval", xml_config_exec_prefix="")
-AC_ARG_ENABLE(xmltest,
- [ --disable-xmltest Do not try to compile and run a test LIBXML program],,
- enable_xmltest=yes)
-
- if test x$xml_config_exec_prefix != x ; then
- xml_config_args="$xml_config_args --exec-prefix=$xml_config_exec_prefix"
- if test x${XML2_CONFIG+set} != xset ; then
- XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config
- fi
- fi
- if test x$xml_config_prefix != x ; then
- xml_config_args="$xml_config_args --prefix=$xml_config_prefix"
- if test x${XML2_CONFIG+set} != xset ; then
- XML2_CONFIG=$xml_config_prefix/bin/xml2-config
- fi
- fi
-
- AC_PATH_PROG(XML2_CONFIG, xml2-config, no)
- min_xml_version=ifelse([$1], ,2.0.0,[$1])
- AC_MSG_CHECKING(for libxml - version >= $min_xml_version)
- no_xml=""
- if test "$XML2_CONFIG" = "no" ; then
- no_xml=yes
- else
- XML_CFLAGS=`$XML2_CONFIG $xml_config_args --cflags`
- XML_LIBS=`$XML2_CONFIG $xml_config_args --libs`
- xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \
- sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
- xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \
- sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
- xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \
- sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
- if test "x$enable_xmltest" = "xyes" ; then
- ac_save_CFLAGS="$CFLAGS"
- ac_save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $XML_CFLAGS"
- LIBS="$XML_LIBS $LIBS"
-dnl
-dnl Now check if the installed libxml is sufficiently new.
-dnl (Also sanity checks the results of xml2-config to some extent)
-dnl
- rm -f conf.xmltest
- AC_TRY_RUN([
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <libxml/xmlversion.h>
-
-int
-main()
-{
- int xml_major_version, xml_minor_version, xml_micro_version;
- int major, minor, micro;
- char *tmp_version;
-
- system("touch conf.xmltest");
-
- /* Capture xml2-config output via autoconf/configure variables */
- /* HP/UX 9 (%@#!) writes to sscanf strings */
- tmp_version = (char *)strdup("$min_xml_version");
- if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
- printf("%s, bad version string from xml2-config\n", "$min_xml_version");
- exit(1);
- }
- free(tmp_version);
-
- /* Capture the version information from the header files */
- tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION);
- if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) {
- printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION");
- exit(1);
- }
- free(tmp_version);
-
- /* Compare xml2-config output to the libxml headers */
- if ((xml_major_version != $xml_config_major_version) ||
- (xml_minor_version != $xml_config_minor_version) ||
- (xml_micro_version != $xml_config_micro_version))
- {
- printf("*** libxml header files (version %d.%d.%d) do not match\n",
- xml_major_version, xml_minor_version, xml_micro_version);
- printf("*** xml2-config (version %d.%d.%d)\n",
- $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version);
- return 1;
- }
-/* Compare the headers to the library to make sure we match */
- /* Less than ideal -- doesn't provide us with return value feedback,
- * only exits if there's a serious mismatch between header and library.
- */
- LIBXML_TEST_VERSION;
-
- /* Test that the library is greater than our minimum version */
- if ((xml_major_version > major) ||
- ((xml_major_version == major) && (xml_minor_version > minor)) ||
- ((xml_major_version == major) && (xml_minor_version == minor) &&
- (xml_micro_version >= micro)))
- {
- return 0;
- }
- else
- {
- printf("\n*** An old version of libxml (%d.%d.%d) was found.\n",
- xml_major_version, xml_minor_version, xml_micro_version);
- printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n",
- major, minor, micro);
- printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n");
- printf("***\n");
- printf("*** If you have already installed a sufficiently new version, this error\n");
- printf("*** probably means that the wrong copy of the xml2-config shell script is\n");
- printf("*** being found. The easiest way to fix this is to remove the old version\n");
- printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n");
- printf("*** correct copy of xml2-config. (In this case, you will have to\n");
- printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
- printf("*** so that the correct libraries are found at run-time))\n");
- }
- return 1;
-}
-],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
- CFLAGS="$ac_save_CFLAGS"
- LIBS="$ac_save_LIBS"
- fi
- fi
-
- if test "x$no_xml" = x ; then
- AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version))
- ifelse([$2], , :, [$2])
- else
- AC_MSG_RESULT(no)
- if test "$XML2_CONFIG" = "no" ; then
- echo "*** The xml2-config script installed by LIBXML could not be found"
- echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in"
- echo "*** your path, or set the XML2_CONFIG environment variable to the"
- echo "*** full path to xml2-config."
- else
- if test -f conf.xmltest ; then
- :
- else
- echo "*** Could not run libxml test program, checking why..."
- CFLAGS="$CFLAGS $XML_CFLAGS"
- LIBS="$LIBS $XML_LIBS"
- AC_TRY_LINK([
-#include <libxml/xmlversion.h>
-#include <stdio.h>
-], [ LIBXML_TEST_VERSION; return 0;],
- [ echo "*** The test program compiled, but did not run. This usually means"
- echo "*** that the run-time linker is not finding LIBXML or finding the wrong"
- echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your"
- echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
- echo "*** to the installed location Also, make sure you have run ldconfig if that"
- echo "*** is required on your system"
- echo "***"
- echo "*** If you have an old version installed, it is best to remove it, although"
- echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
- [ echo "*** The test program failed to compile or link. See the file config.log for the"
- echo "*** exact error that occured. This usually means LIBXML was incorrectly installed"
- echo "*** or that you have moved LIBXML since it was installed. In the latter case, you"
- echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ])
- CFLAGS="$ac_save_CFLAGS"
- LIBS="$ac_save_LIBS"
- fi
- fi
-
- XML_CFLAGS=""
- XML_LIBS=""
- ifelse([$3], , :, [$3])
- fi
- AC_SUBST(XML_CFLAGS)
- AC_SUBST(XML_LIBS)
- rm -f conf.xmltest
-])
-
-# =========================================================================
-# AM_PATH_MYSQL : MySQL library
-
-dnl AM_PATH_MYSQL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
-dnl Test for MYSQL, and define MYSQL_CFLAGS and MYSQL_LIBS
-dnl
-AC_DEFUN(AM_PATH_MYSQL,
-[dnl
-dnl Get the cflags and libraries from the mysql_config script
-dnl
-AC_ARG_WITH(mysql-prefix,[ --with-mysql-prefix=PFX Prefix where MYSQL is installed (optional)],
- mysql_prefix="$withval", mysql_prefix="")
-AC_ARG_WITH(mysql-exec-prefix,[ --with-mysql-exec-prefix=PFX Exec prefix where MYSQL is installed (optional)],
- mysql_exec_prefix="$withval", mysql_exec_prefix="")
-
- if test x$mysql_exec_prefix != x ; then
- mysql_args="$mysql_args --exec-prefix=$mysql_exec_prefix"
- if test x${MYSQL_CONFIG+set} != xset ; then
- MYSQL_CONFIG=$mysql_exec_prefix/bin/mysql_config
- fi
- fi
- if test x$mysql_prefix != x ; then
- mysql_args="$mysql_args --prefix=$mysql_prefix"
- if test x${MYSQL_CONFIG+set} != xset ; then
- MYSQL_CONFIG=$mysql_prefix/bin/mysql_config
- fi
- fi
-
- AC_REQUIRE([AC_CANONICAL_TARGET])
- AC_PATH_PROG(MYSQL_CONFIG, mysql_config, no)
- AC_MSG_CHECKING(for MYSQL)
- no_mysql=""
- if test "$MYSQL_CONFIG" = "no" ; then
- MYSQL_CFLAGS=""
- MYSQL_LIBS=""
- AC_MSG_RESULT(no)
- ifelse([$2], , :, [$2])
- else
- MYSQL_CFLAGS=`$MYSQL_CONFIG $mysqlconf_args --cflags | sed -e "s/'//g"`
- MYSQL_LIBS=`$MYSQL_CONFIG $mysqlconf_args --libs | sed -e "s/'//g"`
- AC_MSG_RESULT(yes)
- ifelse([$1], , :, [$1])
- fi
- AC_SUBST(MYSQL_CFLAGS)
- AC_SUBST(MYSQL_LIBS)
-])
-
-# =========================================================================
-# AM_PATH_PGSQL : pgSQL library
-
-dnl AM_PATH_PGSQL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
-dnl Test for PGSQL, and define PGSQL_CFLAGS and PGSQL_LIBS
-dnl
-AC_DEFUN(AM_PATH_PGSQL,
-[dnl
-dnl Get the cflags and libraries from the pg_config script
-dnl
-AC_ARG_WITH(pgsql-prefix,[ --with-pgsql-prefix=PFX Prefix where PostgreSQL is installed (optional)],
- pgsql_prefix="$withval", pgsql_prefix="")
-AC_ARG_WITH(pgsql-exec-prefix,[ --with-pgsql-exec-prefix=PFX Exec prefix where PostgreSQL is installed (optional)],
- pgsql_exec_prefix="$withval", pgsql_exec_prefix="")
-
- if test x$pgsql_exec_prefix != x ; then
- if test x${PGSQL_CONFIG+set} != xset ; then
- PGSQL_CONFIG=$pgsql_exec_prefix/bin/pg_config
- fi
- fi
- if test x$pgsql_prefix != x ; then
- if test x${PGSQL_CONFIG+set} != xset ; then
- PGSQL_CONFIG=$pgsql_prefix/bin/pg_config
- fi
- fi
-
- AC_REQUIRE([AC_CANONICAL_TARGET])
- AC_PATH_PROG(PGSQL_CONFIG, pg_config, no, [$PATH:/usr/lib/postgresql/bin])
- AC_MSG_CHECKING(for PGSQL)
- no_pgsql=""
- if test "$PGSQL_CONFIG" = "no" ; then
- PGSQL_CFLAGS=""
- PGSQL_LIBS=""
- AC_MSG_RESULT(no)
- ifelse([$2], , :, [$2])
- else
- PGSQL_CFLAGS=-I`$PGSQL_CONFIG --includedir`
- PGSQL_LIBS="-lpq -L`$PGSQL_CONFIG --libdir`"
- AC_MSG_RESULT(yes)
- ifelse([$1], , :, [$1])
- fi
- AC_SUBST(PGSQL_CFLAGS)
- AC_SUBST(PGSQL_LIBS)
-])
-
dnl Removes -I/usr/include/? from given variable
AC_DEFUN(CFLAGS_REMOVE_USR_INCLUDE,[
ac_new_flags=""
@@ -593,14 +267,33 @@ AC_DEFUN(CFLAGS_REMOVE_USR_INCLUDE,[
done
$1=[$]ac_new_flags
])
-
-dnl Removes -L/usr/lib/? from given variable
+
+dnl Removes '-L/usr/lib[/]', '-Wl,-rpath,/usr/lib[/]'
+dnl and '-Wl,-rpath -Wl,/usr/lib[/]' from given variable
AC_DEFUN(LIB_REMOVE_USR_LIB,[
ac_new_flags=""
+ l=""
for i in [$]$1; do
- case [$]i in
- -L/usr/lib|-L/usr/lib/) ;;
- *) ac_new_flags="[$]ac_new_flags [$]i" ;;
+ case [$]l[$]i in
+ -L/usr/lib) ;;
+ -L/usr/lib/) ;;
+ -Wl,-rpath,/usr/lib) ;;
+ -Wl,-rpath,/usr/lib/) ;;
+ -Wl,-rpath) l=[$]i;;
+ -Wl,-rpath-Wl,/usr/lib) l="";;
+ -Wl,-rpath-Wl,/usr/lib/) l="";;
+ *)
+ s=" "
+ if test x"[$]ac_new_flags" = x""; then
+ s="";
+ fi
+ if test x"[$]l" = x""; then
+ ac_new_flags="[$]ac_new_flags[$]s[$]i";
+ else
+ ac_new_flags="[$]ac_new_flags[$]s[$]l [$]i";
+ fi
+ l=""
+ ;;
esac
done
$1=[$]ac_new_flags
@@ -669,6 +362,23 @@ AC_DEFUN(jm_ICONV,
jm_cv_func_iconv=yes
jm_cv_lib_iconv="iconv")
LIBS="$jm_save_LIBS"
+
+ if test "$jm_cv_lib_iconv" != yes; then
+ jm_save_LIBS="$LIBS"
+ LIBS="$LIBS -lbiconv"
+ AC_TRY_LINK([#include <stdlib.h>
+#include <biconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ jm_cv_lib_iconv=yes
+ jm_cv_func_iconv=yes
+ jm_cv_include="biconv.h"
+ jm_cv_biconv=yes
+ jm_cv_lib_iconv="biconv")
+
+ LIBS="$jm_save_LIBS"
+ fi
fi
fi
fi
@@ -854,9 +564,9 @@ AC_DEFUN([SMB_IS_LIBPTHREAD_LINKED],
dnl SMB_REMOVE_LIB(lib)
dnl Remove the given library from $LIBS
-AC_DEFUN([SMB_REMOVELIB],
+AC_DEFUN([SMB_REMOVE_LIB],
[
- LIBS=`echo $LIBS | sed -es/-l$1//g`
+ LIBS=`echo $LIBS | sed '-es/-l$1//g'`
])
dnl SMB_CHECK_DMAPI([actions if true], [actions if false])
@@ -882,9 +592,15 @@ AC_DEFUN([SMB_CHECK_DMAPI],
[samba_dmapi_libs="-lxdsm"], [])
fi
+ if test x"$samba_dmapi_libs" = x"" ; then
+ AC_CHECK_LIB(dmapi, dm_get_eventlist,
+ [samba_dmapi_libs="-ldmapi"], [])
+ fi
+
+
# Only bother to test ehaders if we have a candidate DMAPI library
if test x"$samba_dmapi_libs" != x"" ; then
- AC_CHECK_HEADERS(sys/dmi.h xfs/dmapi.h sys/jfsdmapi.h sys/dmapi.h)
+ AC_CHECK_HEADERS(sys/dmi.h xfs/dmapi.h sys/jfsdmapi.h sys/dmapi.h dmapi.h)
fi
if test x"$samba_dmapi_libs" != x"" ; then
@@ -902,6 +618,8 @@ AC_DEFUN([SMB_CHECK_DMAPI],
#include <sys/jfsdmapi.h>
#elif defined(HAVE_SYS_DMAPI_H)
#include <sys/dmapi.h>
+#elif defined(HAVE_DMAPI_H)
+#include <dmapi.h>
#endif
],
[
@@ -981,3 +699,98 @@ clockid_t clk = $1;
AC_MSG_RESULT(no)
])
])
+
+dnl SMB_IF_RTSIGNAL_BUG([actions if true],
+dnl [actions if false],
+dnl [actions if cross compiling])
+dnl Test whether we can call sigaction with RT_SIGNAL_NOTIFY and
+dnl RT_SIGNAL_LEASE (also RT_SIGNAL_AIO for good measure, though
+dnl I don't believe that triggers any bug.
+dnl
+dnl See the samba-technical thread titled "Failed to setup
+dnl RT_SIGNAL_NOTIFY handler" for details on the bug in question.
+AC_DEFUN([SMB_IF_RTSIGNAL_BUG],
+[
+ rt_signal_notify_works=yes
+ rt_signal_lease_works=yes
+ rt_signal_aio_works=yes
+
+ AC_MSG_CHECKING(if sigaction works with realtime signals)
+ AC_TRY_RUN(
+ [
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+
+/* from smbd/notify_kernel.c */
+#ifndef RT_SIGNAL_NOTIFY
+#define RT_SIGNAL_NOTIFY (SIGRTMIN+2)
+#endif
+
+/* from smbd/aio.c */
+#ifndef RT_SIGNAL_AIO
+#define RT_SIGNAL_AIO (SIGRTMIN+3)
+#endif
+
+/* from smbd/oplock_linux.c */
+#ifndef RT_SIGNAL_LEASE
+#define RT_SIGNAL_LEASE (SIGRTMIN+1)
+#endif
+
+static void signal_handler(int sig, siginfo_t *info, void *unused)
+{
+ int do_nothing = 0;
+}
+
+int main(void)
+{
+ int result = 0;
+ struct sigaction act = {0};
+
+ act.sa_sigaction = signal_handler;
+ act.sa_flags = SA_SIGINFO;
+ sigemptyset( &act.sa_mask );
+
+ if (sigaction(RT_SIGNAL_LEASE, &act, 0) != 0) {
+ /* Failed to setup RT_SIGNAL_LEASE handler */
+ result += 1;
+ }
+
+ if (sigaction(RT_SIGNAL_NOTIFY, &act, 0) != 0) {
+ /* Failed to setup RT_SIGNAL_NOTIFY handler */
+ result += 10;
+ }
+
+ if (sigaction(RT_SIGNAL_AIO, &act, 0) != 0) {
+ /* Failed to setup RT_SIGNAL_AIO handler */
+ result += 100;
+ }
+
+ /* zero on success */
+ return result;
+}
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ $2
+ ],
+ [
+ AC_MSG_RESULT(no)
+ case "$ac_status" in
+ 1|11|101|111) rt_signal_lease_ok=no ;;
+ esac
+ case "$ac_status" in
+ 10|11|110|111) rt_signal_notify_ok=no ;;
+ esac
+ case "$ac_status" in
+ 100|110|101|111) rt_signal_aio_ok=no ;;
+ esac
+ $2
+ ],
+ [
+ AC_MSG_RESULT(cross)
+ $3
+ ])
+])
+
+m4_include(lib/replace/libreplace.m4)
diff --git a/source/auth/auth.c b/source/auth/auth.c
index 139ba5482b7..0b868b265ed 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -432,7 +432,6 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
{
auth_methods *list = NULL;
auth_methods *t = NULL;
- auth_methods *tmp;
NTSTATUS nt_status;
if (!text_list) {
@@ -445,7 +444,7 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
for (;*text_list; text_list++) {
if (load_auth_module(*auth_context, *text_list, &t)) {
- DLIST_ADD_END(list, t, tmp);
+ DLIST_ADD_END(list, t, auth_methods *);
}
}
diff --git a/source/auth/auth_compat.c b/source/auth/auth_compat.c
index bd5d7f02290..13035eece28 100644
--- a/source/auth/auth_compat.c
+++ b/source/auth/auth_compat.c
@@ -92,18 +92,28 @@ static NTSTATUS pass_check_smb(const char *smb_name,
check if a username/password pair is ok via the auth subsystem.
return True if the password is correct, False otherwise
****************************************************************************/
+
BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
{
DATA_BLOB null_password = data_blob(NULL, 0);
- BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24);
+ BOOL encrypted = (global_encrypted_passwords_negotiated && (password_blob.length == 24 || password_blob.length > 46));
if (encrypted) {
/*
* The password could be either NTLM or plain LM. Try NTLM first,
* but fall-through as required.
- * NTLMv2 makes no sense here.
+ * Vista sends NTLMv2 here - we need to try the client given workgroup.
*/
+ if (get_session_workgroup()) {
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, get_session_workgroup(), null_password, password_blob, null_password, encrypted))) {
+ return True;
+ }
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, get_session_workgroup(), password_blob, null_password, null_password, encrypted))) {
+ return True;
+ }
+ }
+
if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) {
return True;
}
@@ -119,5 +129,3 @@ BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
return False;
}
-
-
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index bedd318c3c3..6468c18cb0e 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -50,6 +50,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
NTSTATUS result;
struct rpc_pipe_client *netlogon_pipe = NULL;
+ *cli = NULL;
+
*pipe_ret = NULL;
/* TODO: Send a SAMLOGON request to determine whether this is a valid
@@ -81,6 +83,11 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
result = NT_STATUS_NO_LOGON_SERVERS;
}
+ if (*cli) {
+ cli_shutdown(*cli);
+ *cli = NULL;
+ }
+
release_server_mutex();
return result;
}
@@ -111,6 +118,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
cli_shutdown(*cli);
+ *cli = NULL;
release_server_mutex();
return result;
}
@@ -126,6 +134,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
"trust account password for domain '%s'\n",
domain));
cli_shutdown(*cli);
+ *cli = NULL;
release_server_mutex();
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
@@ -141,6 +150,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
if (!NT_STATUS_IS_OK(result)) {
cli_shutdown(*cli);
+ *cli = NULL;
release_server_mutex();
return result;
}
@@ -150,6 +160,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
cli_shutdown(*cli);
+ *cli = NULL;
release_server_mutex();
return NT_STATUS_NO_LOGON_SERVERS;
}
@@ -258,6 +269,17 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
if (NT_STATUS_IS_OK(nt_status)) {
(*server_info)->was_mapped |= user_info->was_mapped;
+
+ if ( ! (*server_info)->guest) {
+ /* if a real user check pam account restrictions */
+ /* only really perfomed if "obey pam restriction" is true */
+ nt_status = smb_pam_accountcheck((*server_info)->unix_name);
+ if ( !NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAM account restriction prevents user login\n"));
+ cli_shutdown(cli);
+ return nt_status;
+ }
+ }
}
netsamlogon_cache_store( user_info->smb_name, &info3 );
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 6cf987a48b1..51b145a7608 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -30,7 +30,8 @@
static const uint8 *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
{
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
+ (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
return auth_ntlmssp_state->auth_context->get_ntlm_challenge(auth_ntlmssp_state->auth_context);
}
@@ -41,7 +42,8 @@ static const uint8 *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlms
*/
static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
{
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
+ (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
return auth_context->challenge_may_be_modified;
@@ -53,7 +55,8 @@ static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_s
*/
static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
{
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
+ (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
SMB_ASSERT(challenge->length == 8);
@@ -77,7 +80,8 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state,
static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
{
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
+ (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
auth_usersupplied_info *user_info = NULL;
NTSTATUS nt_status;
BOOL username_was_mapped;
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index ec405dd2be4..847315ef888 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -168,7 +168,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
time_t last_set_time = pdb_get_pass_last_set_time(sampass);
/* check for immediate expiry "must change at next logon" */
- if (must_change_time == 0 && last_set_time != 0) {
+ if (last_set_time == 0) {
DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", pdb_get_username(sampass)));
return NT_STATUS_PASSWORD_MUST_CHANGE;
}
diff --git a/source/auth/auth_script.c b/source/auth/auth_script.c
index ec7264924cd..bdcd7533f93 100644
--- a/source/auth/auth_script.c
+++ b/source/auth/auth_script.c
@@ -69,7 +69,7 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
48 + 1 + /* 24 bytes of challenge going to 48 */
48 + 1;
- secret_str = malloc(secret_str_len);
+ secret_str = (char *)malloc(secret_str_len);
if (!secret_str) {
return NT_STATUS_NO_MEMORY;
}
@@ -132,14 +132,16 @@ static NTSTATUS auth_init_script(struct auth_context *auth_context, const char *
if (param && *param) {
/* we load the 'fallback' module - if script isn't here, call this
module */
- if (!load_auth_module(auth_context, param, (auth_methods **)&(*auth_method)->private_data)) {
+ auth_methods *priv;
+ if (!load_auth_module(auth_context, param, &priv)) {
return NT_STATUS_UNSUCCESSFUL;
}
-
+ (*auth_method)->private_data = (void *)priv;
}
return NT_STATUS_OK;
}
+NTSTATUS auth_script_init(void);
NTSTATUS auth_script_init(void)
{
return smb_register_auth(AUTH_INTERFACE_VERSION, "script", auth_init_script);
diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c
index 7bec1b4128d..c7243e8468b 100644
--- a/source/auth/auth_server.c
+++ b/source/auth/auth_server.c
@@ -39,7 +39,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
char *pserver;
BOOL connected_ok = False;
- if (!(cli = cli_initialise(cli)))
+ if (!(cli = cli_initialise()))
return NULL;
/* security = server just can't function with spnego */
@@ -49,7 +49,8 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
p = pserver;
while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
- standard_sub_basic(current_user_info.smb_name, desthost, sizeof(desthost));
+ standard_sub_basic(current_user_info.smb_name, current_user_info.domain,
+ desthost, sizeof(desthost));
strupper_m(desthost);
if(!resolve_name( desthost, &dest_ip, 0x20)) {
@@ -85,7 +86,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
return NULL;
}
- if (!attempt_netbios_session_request(cli, global_myname(),
+ if (!attempt_netbios_session_request(&cli, global_myname(),
desthost, &dest_ip)) {
release_server_mutex();
DEBUG(1,("password server fails session request\n"));
@@ -94,7 +95,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
}
if (strequal(desthost,myhostname())) {
- exit_server("Password server loop!");
+ exit_server_cleanly("Password server loop!");
}
DEBUG(3,("got session\n"));
@@ -119,8 +120,8 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
this one...
*/
- if (!cli_session_setup(cli, "", "", 0, "", 0,
- "")) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 0, "", 0,
+ ""))) {
DEBUG(0,("%s rejected the initial session setup (%s)\n",
desthost, cli_errstr(cli)));
release_server_mutex();
@@ -129,7 +130,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
}
release_server_mutex();
-
+
DEBUG(3,("password server OK\n"));
return cli;
@@ -240,7 +241,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
return nt_status;
}
- cli = my_private_data;
+ cli = (struct cli_state *)my_private_data;
if (cli) {
} else {
@@ -295,8 +296,12 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
*/
if ((!tested_password_server) && (lp_paranoid_server_security())) {
- if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass),
- (char *)badpass, sizeof(badpass), user_info->domain)) {
+ if (NT_STATUS_IS_OK(cli_session_setup(cli, baduser,
+ (char *)badpass,
+ sizeof(badpass),
+ (char *)badpass,
+ sizeof(badpass),
+ user_info->domain))) {
/*
* We connected to the password server so we
@@ -342,30 +347,25 @@ use this machine as the password server.\n"));
if (!user_info->encrypted) {
/* Plaintext available */
- if (!cli_session_setup(cli, user_info->smb_name,
- (char *)user_info->plaintext_password.data,
- user_info->plaintext_password.length,
- NULL, 0,
- user_info->domain)) {
- DEBUG(1,("password server %s rejected the password\n", cli->desthost));
- /* Make this cli_nt_error() when the conversion is in */
- nt_status = cli_nt_error(cli);
- } else {
- nt_status = NT_STATUS_OK;
- }
+ nt_status = cli_session_setup(
+ cli, user_info->smb_name,
+ (char *)user_info->plaintext_password.data,
+ user_info->plaintext_password.length,
+ NULL, 0, user_info->domain);
+
} else {
- if (!cli_session_setup(cli, user_info->smb_name,
- (char *)user_info->lm_resp.data,
- user_info->lm_resp.length,
- (char *)user_info->nt_resp.data,
- user_info->nt_resp.length,
- user_info->domain)) {
- DEBUG(1,("password server %s rejected the password\n", cli->desthost));
- /* Make this cli_nt_error() when the conversion is in */
- nt_status = cli_nt_error(cli);
- } else {
- nt_status = NT_STATUS_OK;
- }
+ nt_status = cli_session_setup(
+ cli, user_info->smb_name,
+ (char *)user_info->lm_resp.data,
+ user_info->lm_resp.length,
+ (char *)user_info->nt_resp.data,
+ user_info->nt_resp.length,
+ user_info->domain);
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1,("password server %s rejected the password: %s\n",
+ cli->desthost, nt_errstr(nt_status)));
}
/* if logged in as guest then reject */
@@ -383,7 +383,15 @@ use this machine as the password server.\n"));
if ( (pass = smb_getpwnam( NULL, user_info->internal_username,
real_username, True )) != NULL )
{
- nt_status = make_server_info_pw(server_info, pass->pw_name, pass);
+ /* if a real user check pam account restrictions */
+ /* only really perfomed if "obey pam restriction" is true */
+ nt_status = smb_pam_accountcheck(pass->pw_name);
+ if ( !NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAM account restriction prevents user login\n"));
+ } else {
+
+ nt_status = make_server_info_pw(server_info, pass->pw_name, pass);
+ }
TALLOC_FREE(pass);
}
else
diff --git a/source/auth/auth_unix.c b/source/auth/auth_unix.c
index efe5203b233..837c9323654 100644
--- a/source/auth/auth_unix.c
+++ b/source/auth/auth_unix.c
@@ -110,7 +110,14 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context,
if (NT_STATUS_IS_OK(nt_status)) {
if (pass) {
- make_server_info_pw(server_info, pass->pw_name, pass);
+ /* if a real user check pam account restrictions */
+ /* only really perfomed if "obey pam restriction" is true */
+ nt_status = smb_pam_accountcheck(pass->pw_name);
+ if ( !NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAM account restriction prevents user login\n"));
+ } else {
+ make_server_info_pw(server_info, pass->pw_name, pass);
+ }
} else {
/* we need to do somthing more useful here */
nt_status = NT_STATUS_NO_SUCH_USER;
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 704f0989e3a..1bc65dcaacc 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -496,7 +496,7 @@ NT_USER_TOKEN *get_root_nt_token( void )
if ( token )
return token;
-
+
if ( !(pw = sys_getpwnam( "root" )) ) {
DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
return NULL;
@@ -513,15 +513,9 @@ NT_USER_TOKEN *get_root_nt_token( void )
return token;
}
-static int server_info_dtor(void *p)
+static int server_info_dtor(auth_serversupplied_info *server_info)
{
- auth_serversupplied_info *server_info =
- talloc_get_type_abort(p, auth_serversupplied_info);
-
- if (server_info->sam_account != NULL) {
- TALLOC_FREE(server_info->sam_account);
- }
-
+ TALLOC_FREE(server_info->sam_account);
ZERO_STRUCTP(server_info);
return 0;
}
@@ -611,8 +605,12 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
"for gid %d!\n", gids[i]));
continue;
}
- add_sid_to_array_unique( result, &unix_group_sid,
- &result->sids, &result->num_sids );
+ if (!add_sid_to_array_unique( result, &unix_group_sid,
+ &result->sids, &result->num_sids )) {
+ result->sam_account = NULL; /* Don't free on error exit. */
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
/* For now we throw away the gids and convert via sid_to_gid
@@ -633,12 +631,17 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
* Add alias SIDs from memberships within the partially created token SID list
*/
-static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
+static NTSTATUS add_aliases(const DOM_SID *domain_sid,
struct nt_user_token *token)
{
uint32 *aliases;
size_t i, num_aliases;
NTSTATUS status;
+ TALLOC_CTX *tmp_ctx;
+
+ if (!(tmp_ctx = talloc_init("add_aliases"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
aliases = NULL;
num_aliases = 0;
@@ -651,21 +654,23 @@ static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
nt_errstr(status)));
+ TALLOC_FREE(tmp_ctx);
return status;
}
for (i=0; i<num_aliases; i++) {
DOM_SID alias_sid;
sid_compose(&alias_sid, domain_sid, aliases[i]);
- add_sid_to_array_unique(token, &alias_sid,
+ if (!add_sid_to_array_unique(token, &alias_sid,
&token->user_sids,
- &token->num_sids);
- if (token->user_sids == NULL) {
+ &token->num_sids)) {
DEBUG(0, ("add_sid_to_array failed\n"));
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
}
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
}
@@ -708,7 +713,7 @@ static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token)
/*******************************************************************
*******************************************************************/
-static NTSTATUS add_builtin_administrators( TALLOC_CTX *ctx, struct nt_user_token *token )
+static NTSTATUS add_builtin_administrators( struct nt_user_token *token )
{
DOM_SID domadm;
@@ -731,8 +736,10 @@ static NTSTATUS add_builtin_administrators( TALLOC_CTX *ctx, struct nt_user_toke
/* Add Administrators if the user beloongs to Domain Admins */
if ( nt_token_check_sid( &domadm, token ) ) {
- add_sid_to_array(token, &global_sid_Builtin_Administrators,
- &token->user_sids, &token->num_sids);
+ if (!add_sid_to_array(token, &global_sid_Builtin_Administrators,
+ &token->user_sids, &token->num_sids)) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
return NT_STATUS_OK;
@@ -759,7 +766,7 @@ static NTSTATUS create_builtin_users( void )
sid_append_rid(&dom_users, DOMAIN_GROUP_RID_USERS );
status = pdb_add_aliasmem( &global_sid_Builtin_Users, &dom_users);
if ( !NT_STATUS_IS_OK(status) ) {
- DEBUG(0,("create_builtin_administrators: Failed to add Domain Users to"
+ DEBUG(0,("create_builtin_users: Failed to add Domain Users to"
" Users\n"));
return status;
}
@@ -776,7 +783,7 @@ static NTSTATUS create_builtin_administrators( void )
NTSTATUS status;
DOM_SID dom_admins, root_sid;
fstring root_name;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
TALLOC_CTX *ctx;
BOOL ret;
@@ -829,48 +836,54 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
int num_groupsids,
const DOM_SID *groupsids)
{
- TALLOC_CTX *tmp_ctx;
struct nt_user_token *result = NULL;
int i;
NTSTATUS status;
gid_t gid;
- tmp_ctx = talloc_new(mem_ctx);
- if (tmp_ctx == NULL) {
- DEBUG(0, ("talloc_new failed\n"));
- return NULL;
- }
+ DEBUG(10, ("Create local NT token for %s\n", sid_string_static(user_sid)));
- result = TALLOC_ZERO_P(tmp_ctx, NT_USER_TOKEN);
- if (result == NULL) {
+ if (!(result = TALLOC_ZERO_P(mem_ctx, NT_USER_TOKEN))) {
DEBUG(0, ("talloc failed\n"));
- goto done;
+ return NULL;
}
/* Add the user and primary group sid */
- add_sid_to_array(result, user_sid,
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array(result, user_sid,
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
/* For guest, num_groupsids may be zero. */
if (num_groupsids) {
- add_sid_to_array(result, &groupsids[0],
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array(result, &groupsids[0],
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
}
/* Add in BUILTIN sids */
- add_sid_to_array(result, &global_sid_World,
- &result->user_sids, &result->num_sids);
- add_sid_to_array(result, &global_sid_Network,
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array(result, &global_sid_World,
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
+ if (!add_sid_to_array(result, &global_sid_Network,
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
if (is_guest) {
- add_sid_to_array(result, &global_sid_Builtin_Guests,
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array(result, &global_sid_Builtin_Guests,
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
} else {
- add_sid_to_array(result, &global_sid_Authenticated_Users,
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array(result, &global_sid_Authenticated_Users,
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
}
/* Now the SIDs we got from authentication. These are the ones from
@@ -880,8 +893,10 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
* first group sid as primary above. */
for (i=1; i<num_groupsids; i++) {
- add_sid_to_array_unique(result, &groupsids[i],
- &result->user_sids, &result->num_sids);
+ if (!add_sid_to_array_unique(result, &groupsids[i],
+ &result->user_sids, &result->num_sids)) {
+ return NULL;
+ }
}
/* Deal with the BUILTIN\Administrators group. If the SID can
@@ -902,7 +917,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
unbecome_root();
}
else {
- status = add_builtin_administrators( tmp_ctx, result );
+ status = add_builtin_administrators( result );
if ( !NT_STATUS_IS_OK(status) ) {
/* just log a complaint but do not fail */
DEBUG(3,("create_local_nt_token: failed to check for local Administrators"
@@ -936,31 +951,26 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
/* Now add the aliases. First the one from our local SAM */
- status = add_aliases(tmp_ctx, get_global_sam_sid(), result);
+ status = add_aliases(get_global_sam_sid(), result);
if (!NT_STATUS_IS_OK(status)) {
- result = NULL;
- goto done;
+ TALLOC_FREE(result);
+ return NULL;
}
/* Finally the builtin ones */
- status = add_aliases(tmp_ctx, &global_sid_Builtin, result);
+ status = add_aliases(&global_sid_Builtin, result);
if (!NT_STATUS_IS_OK(status)) {
- result = NULL;
- goto done;
+ TALLOC_FREE(result);
+ return NULL;
}
}
get_privileges_for_sids(&result->privileges, result->user_sids,
result->num_sids);
-
- talloc_steal(mem_ctx, result);
-
- done:
- TALLOC_FREE(tmp_ctx);
return result;
}
@@ -972,7 +982,9 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
NTSTATUS create_local_token(auth_serversupplied_info *server_info)
{
TALLOC_CTX *mem_ctx;
+ struct id_map *ids;
NTSTATUS status;
+ BOOL wb = True;
size_t i;
@@ -982,6 +994,12 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
return NT_STATUS_NO_MEMORY;
}
+ /*
+ * If winbind is not around, we can not make much use of the SIDs the
+ * domain controller provided us with. Likewise if the user name was
+ * mapped to some local unix user.
+ */
+
if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
(server_info->was_mapped)) {
status = create_token_from_username(server_info,
@@ -1013,18 +1031,44 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
server_info->groups = NULL;
/* Start at index 1, where the groups start. */
+ ids = talloc_zero_array(mem_ctx, struct id_map, server_info->ptok->num_sids);
+ for (i = 0; i < server_info->ptok->num_sids-1; i++) {
+ ids[i].sid = &server_info->ptok->user_sids[i + 1]; /* store the sids */
+ }
+
+ if (!winbind_sids_to_unixids(ids, server_info->ptok->num_sids-1)) {
+ DEBUG(2, ("Query to map secondary SIDs failed!\n"));
+ if (!winbind_ping()) {
+ DEBUG(2, ("Winbindd is not running, will try to map SIDs one by one with legacy code\n"));
+ wb = False;
+ }
+ }
- for (i=1; i<server_info->ptok->num_sids; i++) {
- gid_t gid;
- DOM_SID *sid = &server_info->ptok->user_sids[i];
+ for (i = 0; i < server_info->ptok->num_sids-1; i++) {
+ gid_t agid;
- if (!sid_to_gid(sid, &gid)) {
+ if (wb) {
+ if (ids[i].status != ID_MAPPED) {
DEBUG(10, ("Could not convert SID %s to gid, "
- "ignoring it\n", sid_string_static(sid)));
+ "ignoring it\n", sid_string_static(ids[i].sid)));
continue;
}
- add_gid_to_array_unique(server_info, gid, &server_info->groups,
- &server_info->n_groups);
+ if (ids[i].xid.type == ID_TYPE_UID) {
+ DEBUG(10, ("SID %s is a User ID (%u) not a Group ID, "
+ "ignoring it\n", sid_string_static(ids[i].sid), ids[i].xid.id));
+ continue;
+ }
+ agid = (gid_t)ids[i].xid.id;
+ } else {
+ if (! sid_to_gid(ids[i].sid, &agid)) {
+ continue;
+ }
+ }
+ if (!add_gid_to_array_unique(server_info, agid, &server_info->groups,
+ &server_info->n_groups)) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
}
debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
@@ -1063,9 +1107,8 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
NTSTATUS result = NT_STATUS_NO_SUCH_USER;
TALLOC_CTX *tmp_ctx;
DOM_SID user_sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
gid_t *gids;
- DOM_SID primary_group_sid;
DOM_SID *group_sids;
DOM_SID unix_group_sid;
size_t num_group_sids;
@@ -1128,6 +1171,8 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
SMB_ASSERT(num_group_sids > 0);
*gid = gids[0];
+
+ /* Ensure we're returning the found_username on the right context. */
*found_username = talloc_strdup(mem_ctx,
pdb_get_username(sam_acct));
@@ -1177,8 +1222,9 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
SMB_ASSERT(num_group_sids > 0);
*gid = gids[0];
- *found_username = talloc_strdup(mem_ctx, pass->pw_name);
+ /* Ensure we're returning the found_username on the right context. */
+ *found_username = talloc_strdup(mem_ctx, pass->pw_name);
} else {
/* This user is from winbind, force the primary gid to the
@@ -1190,20 +1236,27 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
uint32 dummy;
- sid_copy(&primary_group_sid, &user_sid);
- sid_split_rid(&primary_group_sid, &dummy);
- sid_append_rid(&primary_group_sid, DOMAIN_GROUP_RID_USERS);
+ num_group_sids = 1;
+ group_sids = talloc_array(tmp_ctx, DOM_SID, num_group_sids);
+ if (group_sids == NULL) {
+ DEBUG(1, ("talloc_array failed\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- if (!sid_to_gid(&primary_group_sid, gid)) {
+ sid_copy(&group_sids[0], &user_sid);
+ sid_split_rid(&group_sids[0], &dummy);
+ sid_append_rid(&group_sids[0], DOMAIN_GROUP_RID_USERS);
+
+ if (!sid_to_gid(&group_sids[0], gid)) {
DEBUG(1, ("sid_to_gid(%s) failed\n",
- sid_string_static(&primary_group_sid)));
+ sid_string_static(&group_sids[0])));
goto done;
}
- num_group_sids = 1;
- group_sids = &primary_group_sid;
gids = gid;
+ /* Ensure we're returning the found_username on the right context. */
*found_username = talloc_strdup(mem_ctx, username);
}
@@ -1228,10 +1281,14 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
"for gid %d!\n", gids[i]));
continue;
}
- add_sid_to_array_unique( mem_ctx, &unix_group_sid,
- &group_sids, &num_group_sids );
+ if (!add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
+ &group_sids, &num_group_sids )) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
+ /* Ensure we're creating the nt_token on the right context. */
*token = create_local_nt_token(mem_ctx, &user_sid,
is_guest, num_group_sids, group_sids);
@@ -1252,6 +1309,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
Expensive helper function to figure out whether a user given its name is
member of a particular group.
***************************************************************************/
+
BOOL user_in_group_sid(const char *username, const DOM_SID *group_sid)
{
NTSTATUS status;
@@ -1377,7 +1435,7 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf
struct samu *sampass = NULL;
DOM_SID guest_sid;
BOOL ret;
- static const char zeros[16];
+ static const char zeros[16] = { 0, };
if ( !(sampass = samu_new( NULL )) ) {
return NT_STATUS_NO_MEMORY;
@@ -1432,8 +1490,8 @@ static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
dst->gid = src->gid;
dst->n_groups = src->n_groups;
if (src->n_groups != 0) {
- dst->groups = talloc_memdup(dst, src->groups,
- sizeof(gid_t)*dst->n_groups);
+ dst->groups = (gid_t *)talloc_memdup(
+ dst, src->groups, sizeof(gid_t)*dst->n_groups);
} else {
dst->groups = NULL;
}
@@ -1489,6 +1547,66 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
}
+BOOL copy_current_user(struct current_user *dst, struct current_user *src)
+{
+ gid_t *groups;
+ NT_USER_TOKEN *nt_token;
+
+ groups = (gid_t *)memdup(src->ut.groups,
+ sizeof(gid_t) * src->ut.ngroups);
+ if ((src->ut.ngroups != 0) && (groups == NULL)) {
+ return False;
+ }
+
+ nt_token = dup_nt_token(NULL, src->nt_user_token);
+ if (nt_token == NULL) {
+ SAFE_FREE(groups);
+ return False;
+ }
+
+ dst->conn = src->conn;
+ dst->vuid = src->vuid;
+ dst->ut.uid = src->ut.uid;
+ dst->ut.gid = src->ut.gid;
+ dst->ut.ngroups = src->ut.ngroups;
+ dst->ut.groups = groups;
+ dst->nt_user_token = nt_token;
+ return True;
+}
+
+BOOL set_current_user_guest(struct current_user *dst)
+{
+ gid_t *groups;
+ NT_USER_TOKEN *nt_token;
+
+ groups = (gid_t *)memdup(guest_info->groups,
+ sizeof(gid_t) * guest_info->n_groups);
+ if (groups == NULL) {
+ return False;
+ }
+
+ nt_token = dup_nt_token(NULL, guest_info->ptok);
+ if (nt_token == NULL) {
+ SAFE_FREE(groups);
+ return False;
+ }
+
+ TALLOC_FREE(dst->nt_user_token);
+ SAFE_FREE(dst->ut.groups);
+
+ /* dst->conn is never really dereferenced, it's only tested for
+ * equality in uid.c */
+ dst->conn = NULL;
+
+ dst->vuid = UID_FIELD_INVALID;
+ dst->ut.uid = guest_info->uid;
+ dst->ut.gid = guest_info->gid;
+ dst->ut.ngroups = guest_info->n_groups;
+ dst->ut.groups = groups;
+ dst->nt_user_token = nt_token;
+ return True;
+}
+
/***************************************************************************
Purely internal function for make_server_info_info3
Fill the sam account from getpwnam
@@ -1634,7 +1752,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
auth_serversupplied_info **server_info,
NET_USER_INFO_3 *info3)
{
- static const char zeros[16];
+ static const char zeros[16] = { 0, };
NTSTATUS nt_status = NT_STATUS_OK;
char *found_username;
@@ -1814,8 +1932,11 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
TALLOC_FREE(result);
return NT_STATUS_INVALID_PARAMETER;
}
- add_sid_to_array(result, &sid, &result->sids,
- &result->num_sids);
+ if (!add_sid_to_array(result, &sid, &result->sids,
+ &result->num_sids)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
/* Copy 'other' sids. We need to do sid filtering here to
@@ -1825,9 +1946,12 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
*/
for (i = 0; i < info3->num_other_sids; i++) {
- add_sid_to_array(result, &info3->other_sids[i].sid,
- &result->sids,
- &result->num_sids);
+ if (!add_sid_to_array(result, &info3->other_sids[i].sid,
+ &result->sids,
+ &result->num_sids)) {
+ TALLOC_FREE(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
result->login_server = unistr2_tdup(result,
@@ -1915,7 +2039,7 @@ BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_me
Duplicate a SID token.
****************************************************************************/
-NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, NT_USER_TOKEN *ptoken)
+NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, const NT_USER_TOKEN *ptoken)
{
NT_USER_TOKEN *token;
@@ -1931,8 +2055,8 @@ NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, NT_USER_TOKEN *ptoken)
ZERO_STRUCTP(token);
if (ptoken->user_sids && ptoken->num_sids) {
- token->user_sids = talloc_memdup(token, ptoken->user_sids,
- sizeof(DOM_SID) * ptoken->num_sids );
+ token->user_sids = (DOM_SID *)talloc_memdup(
+ token, ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
if (token->user_sids == NULL) {
DEBUG(0, ("talloc_memdup failed\n"));
@@ -1941,7 +2065,7 @@ NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, NT_USER_TOKEN *ptoken)
}
token->num_sids = ptoken->num_sids;
}
-
+
/* copy the privileges; don't consider failure to be critical here */
if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) {
diff --git a/source/auth/auth_winbind.c b/source/auth/auth_winbind.c
index d8ac348d040..fa56757950d 100644
--- a/source/auth/auth_winbind.c
+++ b/source/auth/auth_winbind.c
@@ -32,7 +32,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response
size_t len = response->length - sizeof(struct winbindd_response);
prs_struct ps;
if (len > 0) {
- info3_ndr = response->extra_data.data;
+ info3_ndr = (uint8 *)response->extra_data.data;
if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) {
return NT_STATUS_NO_MEMORY;
}
@@ -112,7 +112,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
unbecome_root();
if ( result == NSS_STATUS_UNAVAIL ) {
- struct auth_methods *auth_method = my_private_data;
+ struct auth_methods *auth_method =
+ (struct auth_methods *)my_private_data;
if ( auth_method )
return auth_method->auth(auth_context, auth_method->private_data,
@@ -157,10 +158,11 @@ static NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char
if (param && *param) {
/* we load the 'fallback' module - if winbind isn't here, call this
module */
- if (!load_auth_module(auth_context, param, (auth_methods **)&(*auth_method)->private_data)) {
+ auth_methods *priv;
+ if (!load_auth_module(auth_context, param, &priv)) {
return NT_STATUS_UNSUCCESSFUL;
}
-
+ (*auth_method)->private_data = (void *)priv;
}
return NT_STATUS_OK;
}
diff --git a/source/auth/pampass.c b/source/auth/pampass.c
index 26b45c5ff8a..ba11d2e8fc2 100644
--- a/source/auth/pampass.c
+++ b/source/auth/pampass.c
@@ -208,7 +208,6 @@ static struct chat_struct *make_pw_chat(const char *p)
fstring reply;
struct chat_struct *list = NULL;
struct chat_struct *t;
- struct chat_struct *tmp;
while (1) {
t = SMB_MALLOC_P(struct chat_struct);
@@ -219,7 +218,7 @@ static struct chat_struct *make_pw_chat(const char *p)
ZERO_STRUCTP(t);
- DLIST_ADD_END(list, t, tmp);
+ DLIST_ADD_END(list, t, struct chat_struct*);
if (!next_token(&p, prompt, NULL, sizeof(fstring)))
break;
@@ -511,7 +510,7 @@ static NTSTATUS smb_pam_auth(pam_handle_t *pamh, const char *user)
pam_error = pam_authenticate(pamh, PAM_SILENT | lp_null_passwords() ? 0 : PAM_DISALLOW_NULL_AUTHTOK);
switch( pam_error ){
case PAM_AUTH_ERR:
- DEBUG(2, ("smb_pam_auth: PAM: Athentication Error for user %s\n", user));
+ DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
break;
case PAM_CRED_INSUFFICIENT:
DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
diff --git a/source/autogen.sh b/source/autogen.sh
index 3422d7cebfa..4d3488c9a48 100755
--- a/source/autogen.sh
+++ b/source/autogen.sh
@@ -4,8 +4,8 @@
## insert all possible names (only works with
## autoconf 2.x
-TESTAUTOHEADER="autoheader autoheader-2.53 autoheader2.50"
-TESTAUTOCONF="autoconf autoconf-2.53 autoconf2.50"
+TESTAUTOHEADER="autoheader autoheader-2.53 autoheader2.50 autoheader259 autoheader253"
+TESTAUTOCONF="autoconf autoconf-2.53 autoconf2.50 autoconf259 autoconf253"
AUTOHEADERFOUND="0"
AUTOCONFFOUND="0"
@@ -53,11 +53,13 @@ echo "$0: running script/mkversion.sh"
rm -rf autom4te*.cache
rm -f configure include/config.h*
-echo "$0: running $AUTOHEADER"
-$AUTOHEADER || exit 1
+IPATHS="-I. -Ilib/replace"
-echo "$0: running $AUTOCONF"
-$AUTOCONF || exit 1
+echo "$0: running $AUTOHEADER $IPATHS"
+$AUTOHEADER $IPATHS || exit 1
+
+echo "$0: running $AUTOCONF $IPATHS"
+$AUTOCONF $IPATHS || exit 1
rm -rf autom4te*.cache
diff --git a/source/client/client.c b/source/client/client.c
index 522048dc74e..8ed3f1dc21e 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -23,6 +23,7 @@
#include "includes.h"
#include "client/client_proto.h"
+#include "include/rpc_client.h"
#ifndef REGISTER
#define REGISTER 0
#endif
@@ -102,7 +103,8 @@ static double dir_total;
struct cli_state *cli;
-
+static char CLI_DIRSEP_CHAR = '\\';
+static char CLI_DIRSEP_STR[] = { '\\', '\0' };
/****************************************************************************
Write to a local file with CR/LF->LF translation if appropriate. Return the
@@ -269,18 +271,18 @@ static int do_cd(char *newdir)
pstrcpy(saved_dir, cur_dir);
- if (*p == '\\')
+ if (*p == CLI_DIRSEP_CHAR)
pstrcpy(cur_dir,p);
else
pstrcat(cur_dir,p);
- if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != '\\')) {
- pstrcat(cur_dir, "\\");
+ if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
+ pstrcat(cur_dir, CLI_DIRSEP_STR);
}
dos_clean_name(cur_dir);
pstrcpy( dname, cur_dir );
- pstrcat(cur_dir,"\\");
+ pstrcat(cur_dir,CLI_DIRSEP_STR);
dos_clean_name(cur_dir);
if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
@@ -290,7 +292,7 @@ static int do_cd(char *newdir)
}
- if ( strequal(targetpath,"\\" ) )
+ if ( strequal(targetpath,CLI_DIRSEP_STR ) )
return 0;
/* Use a trans2_qpathinfo to test directories for modern servers.
@@ -309,7 +311,7 @@ static int do_cd(char *newdir)
goto out;
}
} else {
- pstrcat( targetpath, "\\" );
+ pstrcat( targetpath, CLI_DIRSEP_STR );
dos_clean_name( targetpath );
if ( !cli_chkpath(targetcli, targetpath) ) {
@@ -359,7 +361,7 @@ static BOOL do_this_one(file_info *finfo)
return False;
}
- if (newer_than && finfo->mtime < newer_than) {
+ if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
DEBUG(3,("newer_than %s failed\n", finfo->name));
return(False);
}
@@ -379,16 +381,16 @@ static BOOL do_this_one(file_info *finfo)
static void display_finfo(file_info *finfo)
{
if (do_this_one(finfo)) {
- time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
+ time_t t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
if (!showacls) {
d_printf(" %-30s%7.7s %8.0f %s",
finfo->name,
attrib_string(finfo->mode),
- (double)finfo->size,
- time_to_asc(&t));
+ (double)finfo->size,
+ time_to_asc(&t));
dir_total += finfo->size;
- } else { /* showacls */
- static pstring afname;
+ } else {
+ pstring afname;
int fnum;
/* skip if this is . or .. */
@@ -406,8 +408,8 @@ static void display_finfo(file_info *finfo)
fnum = cli_nt_create(cli, afname, CREATE_ACCESS_READ);
if (fnum == -1) {
DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
- afname,
- cli_errstr( cli)));
+ afname,
+ cli_errstr( cli)));
} else {
SEC_DESC *sd = NULL;
sd = cli_query_secdesc(cli, fnum, ctx);
@@ -470,7 +472,7 @@ static void init_do_list_queue(void)
{
reset_do_list_queue();
do_list_queue_size = 1024;
- do_list_queue = SMB_MALLOC(do_list_queue_size);
+ do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
if (do_list_queue == 0) {
d_printf("malloc fail for size %d\n",
(int)do_list_queue_size);
@@ -514,7 +516,7 @@ static void add_to_do_list_queue(const char* entry)
do_list_queue_size *= 2;
DEBUG(4,("enlarging do_list_queue to %d\n",
(int)do_list_queue_size));
- do_list_queue = SMB_REALLOC(do_list_queue, do_list_queue_size);
+ do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
if (! do_list_queue) {
d_printf("failure enlarging do_list_queue to %d bytes\n",
(int)do_list_queue_size);
@@ -563,7 +565,7 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
/* save the directory */
pstrcpy( f->dir, mask );
- if ( (dir_end = strrchr( f->dir, '\\' )) != NULL ) {
+ if ( (dir_end = strrchr( f->dir, CLI_DIRSEP_CHAR )) != NULL ) {
*dir_end = '\0';
}
@@ -584,7 +586,7 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
pstrcpy(mask2, mntpoint);
pstrcat(mask2, mask);
- p = strrchr_m(mask2,'\\');
+ p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
if (!p)
return;
p[1] = 0;
@@ -651,7 +653,7 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
char* save_ch = 0;
if ((strlen(next_file) >= 2) &&
(next_file[strlen(next_file) - 1] == '*') &&
- (next_file[strlen(next_file) - 2] == '\\')) {
+ (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
save_ch = next_file +
strlen(next_file) - 2;
*save_ch = '\0';
@@ -661,7 +663,7 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
if (!showacls) /* don't disturbe the showacls output */
d_printf("\n%s\n",next_file);
if (save_ch) {
- *save_ch = '\\';
+ *save_ch = CLI_DIRSEP_CHAR;
}
}
}
@@ -694,17 +696,17 @@ static int cmd_dir(void)
int rc;
dir_total = 0;
- if (strcmp(cur_dir, "\\") != 0) {
+ if (strcmp(cur_dir, CLI_DIRSEP_STR) != 0) {
pstrcpy(mask,cur_dir);
- if ((mask[0] != '\0') && (mask[strlen(mask)-1]!='\\'))
- pstrcat(mask,"\\");
+ if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR))
+ pstrcat(mask,CLI_DIRSEP_STR);
} else {
- pstrcpy(mask, "\\");
+ pstrcpy(mask, CLI_DIRSEP_STR);
}
if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
dos_format(p);
- if (*p == '\\')
+ if (*p == CLI_DIRSEP_CHAR)
pstrcpy(mask,p + 1);
else
pstrcat(mask,p);
@@ -735,12 +737,12 @@ static int cmd_du(void)
dir_total = 0;
pstrcpy(mask,cur_dir);
- if ((mask[0] != '\0') && (mask[strlen(mask)-1]!='\\'))
- pstrcat(mask,"\\");
+ if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR))
+ pstrcat(mask,CLI_DIRSEP_STR);
if (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
dos_format(p);
- if (*p == '\\')
+ if (*p == CLI_DIRSEP_CHAR)
pstrcpy(mask,p);
else
pstrcat(mask,p);
@@ -913,7 +915,7 @@ static int cmd_get(void)
char *p;
pstrcpy(rname,cur_dir);
- pstrcat(rname,"\\");
+ pstrcat(rname,CLI_DIRSEP_STR);
p = rname + strlen(rname);
@@ -969,7 +971,7 @@ static void do_mget(file_info *finfo)
pstrcpy(saved_curdir,cur_dir);
pstrcat(cur_dir,finfo->name);
- pstrcat(cur_dir,"\\");
+ pstrcat(cur_dir,CLI_DIRSEP_STR);
unix_format(finfo->name);
if (lowercase)
@@ -1008,7 +1010,7 @@ static int cmd_more(void)
int rc = 0;
pstrcpy(rname,cur_dir);
- pstrcat(rname,"\\");
+ pstrcat(rname,CLI_DIRSEP_STR);
slprintf(lname,sizeof(lname)-1, "%s/smbmore.XXXXXX",tmpdir());
fd = smb_mkstemp(lname);
@@ -1057,10 +1059,10 @@ static int cmd_mget(void)
while (next_token_nr(NULL,p,NULL,sizeof(buf))) {
pstrcpy(mget_mask,cur_dir);
- if ((mget_mask[0] != '\0') && (mget_mask[strlen(mget_mask)-1]!='\\'))
- pstrcat(mget_mask,"\\");
+ if ((mget_mask[0] != '\0') && (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR))
+ pstrcat(mget_mask,CLI_DIRSEP_STR);
- if (*p == '\\')
+ if (*p == CLI_DIRSEP_CHAR)
pstrcpy(mget_mask,p);
else
pstrcat(mget_mask,p);
@@ -1069,8 +1071,8 @@ static int cmd_mget(void)
if (!*mget_mask) {
pstrcpy(mget_mask,cur_dir);
- if(mget_mask[strlen(mget_mask)-1]!='\\')
- pstrcat(mget_mask,"\\");
+ if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)
+ pstrcat(mget_mask,CLI_DIRSEP_STR);
pstrcat(mget_mask,"*");
do_list(mget_mask, attribute,do_mget,False,True);
}
@@ -1163,7 +1165,7 @@ static int cmd_mkdir(void)
if (!cli_chkpath(cli, ddir2)) {
do_mkdir(ddir2);
}
- pstrcat(ddir2,"\\");
+ pstrcat(ddir2,CLI_DIRSEP_STR);
p = strtok(NULL,"/\\");
}
} else {
@@ -1343,7 +1345,7 @@ static int cmd_put(void)
char *p=buf;
pstrcpy(rname,cur_dir);
- pstrcat(rname,"\\");
+ pstrcat(rname,CLI_DIRSEP_STR);
if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
d_printf("put <filename>\n");
@@ -1707,6 +1709,38 @@ static int cmd_del(void)
}
/****************************************************************************
+ Wildcard delete some files.
+****************************************************************************/
+
+static int cmd_wdel(void)
+{
+ pstring mask;
+ pstring buf;
+ uint16 attribute;
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("wdel 0x<attrib> <wcard>\n");
+ return 1;
+ }
+
+ attribute = (uint16)strtol(buf, (char **)NULL, 16);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("wdel 0x<attrib> <wcard>\n");
+ return 1;
+ }
+
+ pstrcpy(mask,cur_dir);
+ pstrcat(mask,buf);
+
+ if (!cli_unlink_full(cli, mask, attribute)) {
+ d_printf("%s deleting remote files %s\n",cli_errstr(cli),mask);
+ }
+ return 0;
+}
+
+
+/****************************************************************************
****************************************************************************/
static int cmd_open(void)
@@ -1715,7 +1749,8 @@ static int cmd_open(void)
pstring buf;
struct cli_state *targetcli;
pstring targetname;
-
+ int fnum;
+
pstrcpy(mask,cur_dir);
if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
@@ -1729,7 +1764,169 @@ static int cmd_open(void)
return 1;
}
- cli_nt_create(targetcli, targetname, FILE_READ_DATA);
+ fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA|FILE_WRITE_DATA);
+ if (fnum == -1) {
+ fnum = cli_nt_create(targetcli, targetname, FILE_READ_DATA);
+ if (fnum != -1) {
+ d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
+ } else {
+ d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+ }
+ } else {
+ d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
+ }
+
+ return 0;
+}
+
+static int cmd_close(void)
+{
+ fstring buf;
+ int fnum;
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("close <fnum>\n");
+ return 1;
+ }
+
+ fnum = atoi(buf);
+ /* We really should use the targetcli here.... */
+ if (!cli_close(cli, fnum)) {
+ d_printf("close %d: %s\n", fnum, cli_errstr(cli));
+ return 1;
+ }
+ return 0;
+}
+
+static int cmd_posix(void)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+ pstring caps;
+
+ if (!SERVER_HAS_UNIX_CIFS(cli)) {
+ d_printf("Server doesn't support UNIX CIFS extensions.\n");
+ return 1;
+ }
+
+ if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) {
+ d_printf("Can't get UNIX CIFS extensions version from server.\n");
+ return 1;
+ }
+
+ d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
+
+ *caps = '\0';
+ if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
+ pstrcat(caps, "locks ");
+ }
+ if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
+ pstrcat(caps, "acls ");
+ }
+ if (caplow & CIFS_UNIX_XATTTR_CAP) {
+ pstrcat(caps, "eas ");
+ }
+ if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ pstrcat(caps, "pathnames ");
+ }
+
+ if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
+ caps[strlen(caps)-1] = '\0';
+ }
+
+ if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
+ d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
+ return 1;
+ }
+
+ d_printf("Selecting server supported CIFS capabilities %s\n", caps);
+
+ if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ CLI_DIRSEP_CHAR = '/';
+ *CLI_DIRSEP_STR = '/';
+ pstrcpy(cur_dir, CLI_DIRSEP_STR);
+ }
+
+ return 0;
+}
+
+static int cmd_lock(void)
+{
+ fstring buf;
+ SMB_BIG_UINT start, len;
+ enum brl_type lock_type;
+ int fnum;
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+ return 1;
+ }
+ fnum = atoi(buf);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ if (*buf == 'r' || *buf == 'R') {
+ lock_type = READ_LOCK;
+ } else if (*buf == 'w' || *buf == 'W') {
+ lock_type = WRITE_LOCK;
+ } else {
+ d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+ if (!cli_posix_lock(cli, fnum, start, len, True, lock_type)) {
+ d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
+ }
+
+ return 0;
+}
+
+static int cmd_unlock(void)
+{
+ fstring buf;
+ SMB_BIG_UINT start, len;
+ int fnum;
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+ return 1;
+ }
+ fnum = atoi(buf);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("unlock <fnum> <hex-start> <hex-len>\n");
+ return 1;
+ }
+
+ len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+
+ if (!cli_posix_unlock(cli, fnum, start, len)) {
+ d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
+ }
return 0;
}
@@ -2532,7 +2729,7 @@ static int cmd_reget(void)
char *p;
pstrcpy(remote_name, cur_dir);
- pstrcat(remote_name, "\\");
+ pstrcat(remote_name, CLI_DIRSEP_STR);
p = remote_name + strlen(remote_name);
@@ -2561,7 +2758,7 @@ static int cmd_reput(void)
SMB_STRUCT_STAT st;
pstrcpy(remote_name, cur_dir);
- pstrcat(remote_name, "\\");
+ pstrcat(remote_name, CLI_DIRSEP_STR);
if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
d_printf("reput <filename>\n");
@@ -2777,10 +2974,10 @@ static int cmd_logon(void)
else
pstrcpy(l_password, buf2);
- if (!cli_session_setup(cli, l_username,
- l_password, strlen(l_password),
- l_password, strlen(l_password),
- lp_workgroup())) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(cli, l_username,
+ l_password, strlen(l_password),
+ l_password, strlen(l_password),
+ lp_workgroup()))) {
d_printf("session setup failed: %s\n", cli_errstr(cli));
return -1;
}
@@ -2846,6 +3043,7 @@ static struct
{"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
{"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
{"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
+ {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
{"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
{"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
@@ -2857,6 +3055,7 @@ static struct
{"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
{"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
{"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
+ {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
{"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
{"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
{"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
@@ -2867,6 +3066,7 @@ static struct
{"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
+ {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
{"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
{"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
{"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
@@ -2888,8 +3088,10 @@ static struct
{"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
{"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
{"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
+ {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
{"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
{"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
+ {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
{"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
{"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
{"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
@@ -3068,10 +3270,17 @@ static char **remote_completion(const char *text, int len)
if (!info.matches) {
return NULL;
}
+
+ /*
+ * We're leaving matches[0] free to fill it later with the text to
+ * display: Either the one single match or the longest common subset
+ * of the matches.
+ */
info.matches[0] = NULL;
+ info.count = 1;
for (i = len-1; i >= 0; i--) {
- if ((text[i] == '/') || (text[i] == '\\')) {
+ if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
break;
}
}
@@ -3090,15 +3299,36 @@ static char **remote_completion(const char *text, int len)
if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0)
goto cleanup;
- if (info.count == 2)
- info.matches[0] = SMB_STRDUP(info.matches[1]);
- else {
- info.matches[0] = SMB_MALLOC(info.samelen+1);
- if (!info.matches[0])
- goto cleanup;
- strncpy(info.matches[0], info.matches[1], info.samelen);
- info.matches[0][info.samelen] = 0;
+ if (info.count == 1) {
+
+ /*
+ * No matches at all, NULL indicates there is nothing
+ */
+
+ SAFE_FREE(info.matches[0]);
+ SAFE_FREE(info.matches);
+ return NULL;
+ }
+
+ if (info.count == 2) {
+
+ /*
+ * Exactly one match in matches[1], indicate this is the one
+ * in matches[0].
+ */
+
+ info.matches[0] = info.matches[1];
+ info.matches[1] = NULL;
+ info.count -= 1;
+ return info.matches;
}
+
+ /*
+ * We got more than one possible match, set the result to the maximum
+ * common subset
+ */
+
+ info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
info.matches[info.count] = NULL;
return info.matches;
@@ -3125,10 +3355,13 @@ static char **completion_fn(const char *text, int start, int end)
sp = strchr(buf, ' ');
if (sp == NULL)
return NULL;
-
- for (i = 0; commands[i].name; i++)
- if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0))
+
+ for (i = 0; commands[i].name; i++) {
+ if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
+ (commands[i].name[sp - buf] == 0)) {
break;
+ }
+ }
if (commands[i].name == NULL)
return NULL;
@@ -3177,7 +3410,7 @@ static char **completion_fn(const char *text, int start, int end)
matches[0] = SMB_STRDUP(matches[1]);
break;
default:
- matches[0] = SMB_MALLOC(samelen+1);
+ matches[0] = (char *)SMB_MALLOC(samelen+1);
if (!matches[0])
goto cleanup;
strncpy(matches[0], matches[1], samelen);
@@ -3415,7 +3648,7 @@ static int do_message_op(void)
msg_port = port ? port : 139;
- if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) ||
+ if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) ||
!cli_connect(cli, server_name, &ip)) {
d_printf("Connection to %s failed\n", desthost);
return 1;
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 14c28acfc5a..f228db11998 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -49,9 +49,9 @@ struct file_info_struct {
uid_t uid;
gid_t gid;
/* These times are normally kept in GMT */
- time_t mtime;
- time_t atime;
- time_t ctime;
+ struct timespec mtime_ts;
+ struct timespec atime_ts;
+ struct timespec ctime_ts;
char *name; /* This is dynamically allocate */
file_info2 *next, *prev; /* Used in the stack ... */
@@ -201,7 +201,11 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid);
oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid);
oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size);
+#ifdef HAVE_LONGLONG
if (size > (SMB_BIG_UINT)077777777777LL) {
+#else
+ if (size > (SMB_BIG_UINT)077777777777) {
+#endif
/* This is a non-POSIX compatible extention to store files
greater than 8GB. */
@@ -308,8 +312,9 @@ of link other than a GNUtar Longlink - ignoring\n"));
* We only get the modification time of the file; set the creation time
* from the mod. time, and the access time to current time
*/
- finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
- finfo->atime = time(NULL);
+ finfo->mtime_ts = finfo->ctime_ts =
+ convert_time_t_to_timespec((time_t)strtol(hb->dbuf.mtime, NULL, 8));
+ finfo->atime_ts = convert_time_t_to_timespec(time(NULL));
finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
return True;
@@ -383,7 +388,7 @@ static void initarbuf(void)
{
/* initialize tar buffer */
tbufsiz=blocksize*TBLOCK;
- tarbuf=SMB_MALLOC(tbufsiz); /* FIXME: We might not get the buffer */
+ tarbuf=(char *)SMB_MALLOC(tbufsiz); /* FIXME: We might not get the buffer */
/* reset tar buffer pointer and tar file counter and total dumped */
tp=0; ntarf=0; ttarf=0;
@@ -621,18 +626,18 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
finfo.mode = finfo1 -> mode;
finfo.uid = finfo1 -> uid;
finfo.gid = finfo1 -> gid;
- finfo.mtime = finfo1 -> mtime;
- finfo.atime = finfo1 -> atime;
- finfo.ctime = finfo1 -> ctime;
+ finfo.mtime_ts = finfo1 -> mtime_ts;
+ finfo.atime_ts = finfo1 -> atime_ts;
+ finfo.ctime_ts = finfo1 -> ctime_ts;
finfo.name = finfo1 -> name;
} else {
finfo.size = def_finfo.size;
finfo.mode = def_finfo.mode;
finfo.uid = def_finfo.uid;
finfo.gid = def_finfo.gid;
- finfo.mtime = def_finfo.mtime;
- finfo.atime = def_finfo.atime;
- finfo.ctime = def_finfo.ctime;
+ finfo.mtime_ts = def_finfo.mtime_ts;
+ finfo.atime_ts = def_finfo.atime_ts;
+ finfo.ctime_ts = def_finfo.ctime_ts;
finfo.name = def_finfo.name;
}
@@ -663,11 +668,14 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
safe_strcpy(finfo.name,rname, strlen(rname));
if (!finfo1) {
- if (!cli_getattrE(cli, fnum, &finfo.mode, &finfo.size, NULL, &finfo.atime, &finfo.mtime)) {
+ time_t atime, mtime;
+ if (!cli_getattrE(cli, fnum, &finfo.mode, &finfo.size, NULL, &atime, &mtime)) {
DEBUG(0, ("getattrE: %s\n", cli_errstr(cli)));
return;
}
- finfo.ctime = finfo.mtime;
+ finfo.atime_ts = convert_time_t_to_timespec(atime);
+ finfo.mtime_ts = convert_time_t_to_timespec(mtime);
+ finfo.ctime_ts = finfo.mtime_ts;
}
DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
@@ -703,7 +711,8 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
/* Only if the first read succeeds, write out the tar header. */
if (!wrote_tar_header) {
/* write a tar header, don't bother with mode - just set to 100644 */
- writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
+ writetarheader(tarhandle, rname, finfo.size,
+ finfo.mtime_ts.tv_sec, "100644 \0", ftype);
wrote_tar_header = True;
}
@@ -832,7 +841,7 @@ strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
/* write a tar directory, don't bother with mode - just set it to
* 40755 */
- writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
+ writetarheader(tarhandle, cur_dir, 0, finfo->mtime_ts.tv_sec, "040755 \0", '5');
if (tar_noisy) {
DEBUG(0,(" directory %s\n", cur_dir));
}
@@ -1030,7 +1039,7 @@ static int get_file(file_info2 finfo)
/* Now we update the creation date ... */
DEBUG(5, ("Updating creation date on %s\n", finfo.name));
- if (!cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime)) {
+ if (!cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec)) {
if (tar_real_noisy) {
DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
/*return(False); */ /* Ignore, as Win95 does not allow changes */
@@ -1066,7 +1075,7 @@ static char *get_longfilename(file_info2 finfo)
/* finfo.size here is the length of the filename as written by the "/./@LongLink" name
* header call. */
int namesize = finfo.size + strlen(cur_dir) + 2;
- char *longname = SMB_MALLOC(namesize);
+ char *longname = (char *)SMB_MALLOC(namesize);
int offset = 0, left = finfo.size;
BOOL first = True;
@@ -1514,7 +1523,7 @@ static int read_inclusion_file(char *filename)
while ((! error) && (x_fgets(buf, sizeof(buf)-1, inclusion))) {
if (inclusion_buffer == NULL) {
inclusion_buffer_size = 1024;
- if ((inclusion_buffer = SMB_MALLOC(inclusion_buffer_size)) == NULL) {
+ if ((inclusion_buffer = (char *)SMB_MALLOC(inclusion_buffer_size)) == NULL) {
DEBUG(0,("failure allocating buffer to read inclusion file\n"));
error = 1;
break;
@@ -1527,7 +1536,7 @@ static int read_inclusion_file(char *filename)
if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
inclusion_buffer_size *= 2;
- inclusion_buffer = SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
+ inclusion_buffer = (char *)SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
if (!inclusion_buffer) {
DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
inclusion_buffer_size));
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index ac98b992bb2..076001ccc07 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -143,7 +143,7 @@ static int open_cred_file(char * file_name)
fs = fopen(file_name,"r");
if(fs == NULL)
return errno;
- line_buf = malloc(4096);
+ line_buf = (char *)malloc(4096);
if(line_buf == NULL) {
fclose(fs);
return -ENOMEM;
@@ -176,7 +176,7 @@ static int open_cred_file(char * file_name)
exit(1);
} else {
got_user = 1;
- user_name = calloc(1 + length,1);
+ user_name = (char *)calloc(1 + length,1);
/* BB adding free of user_name string before exit,
not really necessary but would be cleaner */
strncpy(user_name,temp_val, length);
@@ -200,7 +200,7 @@ static int open_cred_file(char * file_name)
exit(1);
} else {
if(mountpassword == NULL) {
- mountpassword = calloc(65,1);
+ mountpassword = (char *)calloc(65,1);
} else
memset(mountpassword,0,64);
if(mountpassword) {
@@ -228,7 +228,7 @@ static int open_cred_file(char * file_name)
exit(1);
} else {
if(domain_name == NULL) {
- domain_name = calloc(65,1);
+ domain_name = (char *)calloc(65,1);
} else
memset(domain_name,0,64);
if(domain_name) {
@@ -255,7 +255,7 @@ static int get_password_from_file(int file_descript, char * filename)
char c;
if(mountpassword == NULL)
- mountpassword = calloc(65,1);
+ mountpassword = (char *)calloc(65,1);
else
memset(mountpassword, 0, 64);
@@ -374,7 +374,7 @@ static int parse_options(char ** optionsp, int * filesys_flags)
if(percent_char) {
*percent_char = ',';
if(mountpassword == NULL)
- mountpassword = calloc(65,1);
+ mountpassword = (char *)calloc(65,1);
if(mountpassword) {
if(got_password)
printf("\nmount.cifs warning - password specified twice\n");
@@ -596,7 +596,7 @@ static int parse_options(char ** optionsp, int * filesys_flags)
if (value)
word_len += 1 + strlen(value);
- out = realloc(out, out_len + word_len + 2);
+ out = (char *)realloc(out, out_len + word_len + 2);
if (out == NULL) {
perror("malloc");
exit(1);
@@ -646,7 +646,7 @@ static void check_for_comma(char ** ppasswrd)
return;
}
- new_pass_buf = malloc(len+number_of_commas+1);
+ new_pass_buf = (char *)malloc(len+number_of_commas+1);
if(new_pass_buf == NULL)
return;
@@ -710,7 +710,7 @@ static char * check_for_domain(char **ppuser)
len = strlen(domainnm);
/* reset domainm to new buffer, and copy
domain name into it */
- domainnm = malloc(len+1);
+ domainnm = (char *)malloc(len+1);
if(domainnm == NULL)
return NULL;
@@ -769,7 +769,7 @@ static char * parse_server(char ** punc_name)
share = strchr(unc_name,':');
if(share) {
free_share_name = 1;
- *punc_name = malloc(length+3);
+ *punc_name = (char *)malloc(length+3);
if(*punc_name == NULL) {
/* put the original string back if
no memory left */
@@ -935,10 +935,20 @@ int main(int argc, char ** argv)
++nomtab;
break;
case 'b':
+#ifdef MS_BIND
flags |= MS_BIND;
+#else
+ fprintf(stderr,
+ "option 'b' (MS_BIND) not supported\n");
+#endif
break;
case 'm':
+#ifdef MS_MOVE
flags |= MS_MOVE;
+#else
+ fprintf(stderr,
+ "option 'm' (MS_MOVE) not supported\n");
+#endif
break;
case 'o':
orgoptions = strdup(optarg);
@@ -1020,7 +1030,7 @@ int main(int argc, char ** argv)
break;
case 'p':
if(mountpassword == NULL)
- mountpassword = calloc(65,1);
+ mountpassword = (char *)calloc(65,1);
if(mountpassword) {
got_password = 1;
strncpy(mountpassword,optarg,64);
@@ -1045,7 +1055,7 @@ int main(int argc, char ** argv)
if (getenv("PASSWD")) {
if(mountpassword == NULL)
- mountpassword = calloc(65,1);
+ mountpassword = (char *)calloc(65,1);
if(mountpassword) {
strncpy(mountpassword,getenv("PASSWD"),64);
got_password = 1;
@@ -1065,7 +1075,7 @@ int main(int argc, char ** argv)
}
/* BB save off path and pop after mount returns? */
- resolved_path = malloc(PATH_MAX+1);
+ resolved_path = (char *)malloc(PATH_MAX+1);
if(resolved_path) {
/* Note that if we can not canonicalize the name, we get
another chance to see if it is valid when we chdir to it */
@@ -1131,7 +1141,7 @@ mount_retry:
optlen += strlen(ipaddr) + 4;
if(mountpassword)
optlen += strlen(mountpassword) + 6;
- options = malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */);
+ options = (char *)malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */);
if(options == NULL) {
printf("Could not allocate memory for mount options\n");
@@ -1223,7 +1233,7 @@ mount_retry:
mountent.mnt_fsname = share_name;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = CONST_DISCARD(char *,"cifs");
- mountent.mnt_opts = malloc(220);
+ mountent.mnt_opts = (char *)malloc(220);
if(mountent.mnt_opts) {
char * mount_user = getusername();
memset(mountent.mnt_opts,0,200);
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index fd385ee6817..b7042f99cb2 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -3494,7 +3494,7 @@ static int do_message_op(void)
msg_port = port ? port : 139;
- if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, msg_port) != msg_port) ||
+ if (!(cli=cli_initialise()) || (cli_set_port(cli, msg_port) != msg_port) ||
!cli_connect(cli, server_name, &ip)) {
d_printf("Connection to %s failed\n", desthost);
return 1;
diff --git a/source/client/smbmount.c b/source/client/smbmount.c
index 7a3ccb7630d..805245b634b 100644
--- a/source/client/smbmount.c
+++ b/source/client/smbmount.c
@@ -26,6 +26,8 @@
extern BOOL in_client;
extern pstring user_socket_options;
+extern char *optarg;
+extern int optind;
static pstring credentials;
static pstring my_netbios_name;
@@ -149,7 +151,7 @@ static struct cli_state *do_connection(char *the_service)
if (have_ip) ip = dest_ip;
/* have to open a new connection */
- if (!(c=cli_initialise(NULL)) || (cli_set_port(c, smb_port) != smb_port) ||
+ if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) ||
!cli_connect(c, server_n, &ip)) {
DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n));
if (c) {
@@ -211,14 +213,14 @@ static struct cli_state *do_connection(char *the_service)
c->force_dos_errors = True;
}
- if (!cli_session_setup(c, username,
- password, strlen(password),
- password, strlen(password),
- workgroup)) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
+ password, strlen(password),
+ password, strlen(password),
+ workgroup))) {
/* if a password was not supplied then try again with a
null username */
if (password[0] || !username[0] ||
- !cli_session_setup(c, "", "", 0, "", 0, workgroup)) {
+ !NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0, "", 0, workgroup))) {
DEBUG(0,("%d: session setup failed: %s\n",
sys_getpid(), cli_errstr(c)));
cli_shutdown(c);
@@ -712,7 +714,6 @@ static void parse_mount_smb(int argc, char **argv)
int opt;
char *opts;
char *opteq;
- extern char *optarg;
int val;
char *p;
@@ -862,8 +863,6 @@ static void parse_mount_smb(int argc, char **argv)
****************************************************************************/
int main(int argc,char *argv[])
{
- extern char *optarg;
- extern int optind;
char *p;
DEBUGLEVEL = 1;
diff --git a/source/client/smbspool.c b/source/client/smbspool.c
index c9a7fbe10ef..5783cbe1381 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -429,9 +429,10 @@ static struct cli_state
}
- if (!cli_session_setup(cli, username, password, strlen(password)+1,
- password, strlen(password)+1,
- workgroup))
+ if (!NT_STATUS_IS_OK(cli_session_setup(cli, username,
+ password, strlen(password)+1,
+ password, strlen(password)+1,
+ workgroup)))
{
fprintf(stderr,"ERROR: Session setup failed: %s\n", cli_errstr(cli));
if (NT_STATUS_V(cli_nt_error(cli)) ==
diff --git a/source/client/umount.cifs.c b/source/client/umount.cifs.c
index e762be8f062..3869e3439fc 100644
--- a/source/client/umount.cifs.c
+++ b/source/client/umount.cifs.c
@@ -138,7 +138,7 @@ static int umount_check_perm(char * dir)
return rc;
}
-int lock_mtab(void)
+static int lock_mtab(void)
{
int rc;
@@ -151,12 +151,12 @@ int lock_mtab(void)
}
-void unlock_mtab(void)
+static void unlock_mtab(void)
{
unlink(MOUNTED_LOCK);
}
-int remove_from_mtab(char * mountpoint)
+static int remove_from_mtab(char * mountpoint)
{
int rc;
int num_matches;
diff --git a/source/configure.developer b/source/configure.developer
index a7074acfd3a..b8cf6d68b10 100755
--- a/source/configure.developer
+++ b/source/configure.developer
@@ -1,2 +1,5 @@
#!/bin/sh
-`dirname $0`/configure --enable-developer "$@"
+`dirname $0`/configure -C \
+ --enable-developer \
+ --enable-socket-wrapper \
+ "$@"
diff --git a/source/configure.in b/source/configure.in
index 879f6f2909b..8f07871bbe9 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -4,9 +4,7 @@ dnl We must use autotools 2.53 or above
AC_PREREQ(2.53)
AC_INIT(include/includes.h)
AC_CONFIG_HEADER(include/config.h)
-
-AC_DISABLE_STATIC
-AC_ENABLE_SHARED
+AC_DEFINE(CONFIG_H_IS_FROM_SAMBA,1,[Marker for samba's config.h])
SMB_VERSION_STRING=`cat $srcdir/include/version.h | grep 'SAMBA_VERSION_OFFICIAL_STRING' | cut -d '"' -f2`
echo "SAMBA VERSION: ${SMB_VERSION_STRING}"
@@ -16,6 +14,11 @@ if test -n "${SAMBA_VERSION_SVN_REVISION}";then
echo "BUILD REVISION: ${SAMBA_VERSION_SVN_REVISION}"
fi
+AC_LIBREPLACE_LOCATION_CHECKS
+
+AC_DISABLE_STATIC
+AC_ENABLE_SHARED
+
#################################################
# Directory handling stuff to support both the
# legacy SAMBA directories and FHS compliant
@@ -227,6 +230,20 @@ do
done
])
+SAMBA_CPPFLAGS="-Iinclude -I${srcdir-.}/include -I. -I${srcdir-.}"
+SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/lib/replace"
+SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/lib/talloc"
+SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/tdb/include"
+SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/libaddns"
+SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/librpc"
+
+SAMBA_CONFIGURE_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/popt"
+
+## cleanup the $(srcdir) in the Makefile if we are outside of the tree
+if test "x${srcdir-.}" != "x."; then
+ SAMBA_CPPFLAGS=`echo ${SAMBA_CPPFLAGS} | sed -e "s;${srcdir};\$\(srcdir\);g"`
+fi
+
AC_SUBST(configdir)
AC_SUBST(lockdir)
AC_SUBST(piddir)
@@ -239,14 +256,13 @@ AC_SUBST(rootsbindir)
AC_SUBST(pammodulesdir)
dnl Unique-to-Samba variables we'll be playing with.
+AC_SUBST(SAMBA_CPPFLAGS)
AC_SUBST(SHELL)
AC_SUBST(LDSHFLAGS)
AC_SUBST(SONAMEFLAG)
AC_SUBST(SHLD)
AC_SUBST(HOST_OS)
-AC_SUBST(PICFLAGS)
-AC_SUBST(PICSUFFIX)
-AC_SUBST(libc_cv_fpie)
+AC_SUBST(PICFLAG)
AC_SUBST(PIE_CFLAGS)
AC_SUBST(PIE_LDFLAGS)
AC_SUBST(SHLIBEXT)
@@ -258,11 +274,16 @@ AC_SUBST(INSTALL_LIBMSRPC)
AC_SUBST(UNINSTALL_LIBMSRPC)
AC_SUBST(LIBMSRPC_SHARED)
AC_SUBST(LIBMSRPC)
+AC_SUBST(INSTALL_LIBADDNS)
+AC_SUBST(UNINSTALL_LIBADDNS)
+AC_SUBST(LIBADDNS_SHARED)
+AC_SUBST(LIBADDNS)
AC_SUBST(INSTALL_LIBSMBCLIENT)
AC_SUBST(UNINSTALL_LIBSMBCLIENT)
AC_SUBST(LIBSMBCLIENT_SHARED)
AC_SUBST(LIBSMBCLIENT)
AC_SUBST(INSTALL_LIBSMBSHAREMODES)
+AC_SUBST(UNINSTALL_LIBSMBSHAREMODES)
AC_SUBST(LIBSMBSHAREMODES_SHARED)
AC_SUBST(LIBSMBSHAREMODES)
AC_SUBST(PRINT_LIBS)
@@ -271,14 +292,12 @@ AC_SUBST(ACL_LIBS)
AC_SUBST(PASSDB_LIBS)
AC_SUBST(IDMAP_LIBS)
AC_SUBST(KRB5_LIBS)
+AC_SUBST(UUID_LIBS)
AC_SUBST(LDAP_LIBS)
AC_SUBST(SHLIB_PROGS)
AC_SUBST(PAM_MODULES)
AC_SUBST(INSTALL_PAM_MODULES)
AC_SUBST(UNINSTALL_PAM_MODULES)
-AC_SUBST(SMBWRAPPER)
-AC_SUBST(SMBWRAP_OBJS)
-AC_SUBST(SMBWRAP_INC)
AC_SUBST(EXTRA_BIN_PROGS)
AC_SUBST(CIFSMOUNT_PROGS)
AC_SUBST(INSTALL_CIFSMOUNT)
@@ -288,44 +307,28 @@ AC_SUBST(EXTRA_ALL_TARGETS)
AC_SUBST(CONFIG_LIBS)
AC_SUBST(NSCD_LIBS)
-# Set defaults
-PIE_CFLAGS=""
-PIE_LDFLAGS=""
-AC_ARG_ENABLE(pie, [ --enable-pie Turn on pie support if available (default=yes)])
-
-if test "x$enable_pie" != xno
-then
- AC_CACHE_CHECK(for -fPIE, libc_cv_fpie, [dnl
- cat > conftest.c <<EOF
-int foo;
-main () { return 0;}
-EOF
- if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -pie -fPIE -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD])
- then
- libc_cv_fpie=yes
- PIE_CFLAGS="-fPIE"
- PIE_LDFLAGS="-pie"
- fi
- rm -f conftest*])
-fi
-if test "x$PIE_CFLAGS" = x
-then
- libc_cv_fpie=no
-fi
-
+## check for --enable-debug first before checking CFLAGS before
+## so that we don't mix -O and -g
AC_ARG_ENABLE(debug,
[ --enable-debug Turn on compiler debugging information (default=no)],
[if eval "test x$enable_debug = xyes"; then
CFLAGS="${CFLAGS} -g"
fi])
-AC_SUBST(SOCKWRAP)
-AC_ARG_ENABLE(socket-wrapper,
-[ --enable-socket-wrapper Turn on socket wrapper library (default=no)],
- [if eval "test x$enable_socket_wrapper = xyes"; then
- AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library])
- SOCKWRAP="\$(SOCKET_WRAPPER_OBJ)"
- fi])
+# compile with optimization and without debugging by default, but
+# allow people to set their own preference.
+# do this here since AC_CACHE_CHECK apparently sets the CFLAGS to "-g -O2"
+# if it has no value. This prevent *very* large debug binaries from occurring
+# by default.
+if test "x$CFLAGS" = x; then
+ CFLAGS="-O"
+fi
+
+CFLAGS="${CFLAGS} -D_SAMBA_BUILD_=3"
+
+AC_LIBREPLACE_CC_CHECKS
+
+m4_include(lib/socket_wrapper/config.m4)
#################################################
# set prefix for 'make test'
@@ -362,17 +365,6 @@ AC_ARG_WITH(smbtorture4_path,
esac
])
-# compile with optimization and without debugging by default, but
-# allow people to set their own preference.
-# do this here since AC_CACHE_CHECK apparently sets the CFLAGS to "-g -O2"
-# if it has no value. This prevent *very* large debug binaries from occurring
-# by default.
-if test "x$CFLAGS" = x; then
- CFLAGS="-O"
-fi
-
-CFLAGS="${CFLAGS} -D_SAMBA_BUILD_"
-
AC_ARG_ENABLE(developer, [ --enable-developer Turn on developer warnings and debugging (default=no)],
[if eval "test x$enable_developer = xyes"; then
developer=yes
@@ -432,18 +424,6 @@ AC_ARG_WITH(profiling-data,
dnl Checks for programs.
-##
-## for some reason this macro resets the CFLAGS
-## so save and restore
-##
-OLD_CFLAGS=${CFLAGS}
-AC_PROG_CC
-CFLAGS=${OLD_CFLAGS}
-
-OLD_CFLAGS=${CFLAGS}
-AC_PROG_CPP
-CFLAGS=${OLD_CFLAGS}
-
AC_PROG_INSTALL
AC_PROG_AWK
AC_PATH_PROG(PERL, perl)
@@ -486,9 +466,6 @@ if test "$ac_cv_prog_gnu_ld" = "yes"; then
fi
fi
-dnl needed before AC_TRY_COMPILE
-AC_ISC_POSIX
-
dnl look for executable suffix
AC_EXEEXT
@@ -533,6 +510,42 @@ if test x"$samba_cv_volatile" = x"yes"; then
AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile])
fi
+############################################
+# check if the compiler can handle negative enum values
+# and don't truncate the values to INT_MAX
+# a runtime test is needed here
+AC_SUBST(PIDL_ARGS)
+AC_CACHE_CHECK([that the C compiler understands negative enum values],SMB_BUILD_CC_NEGATIVE_ENUM_VALUES, [
+ AC_TRY_RUN(
+[
+ #include <stdio.h>
+ enum negative_values { NEGATIVE_VALUE = 0xFFFFFFFF };
+ int main(void) {
+ enum negative_values v1 = NEGATIVE_VALUE;
+ unsigned v2 = NEGATIVE_VALUE;
+
+ if (v1 != 0xFFFFFFFF) {
+ printf("%u != 0xFFFFFFFF\n", v1);
+ return 1;
+ }
+ if (v2 != 0xFFFFFFFF) {
+ printf("%u != 0xFFFFFFFF\n", v2);
+ return 1;
+ }
+
+ return 0;
+ }
+],
+ SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=yes,SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=no)])
+if test x"$SMB_BUILD_CC_NEGATIVE_ENUM_VALUES" != x"yes"; then
+ AC_MSG_WARN([using --unit-enums for pidl])
+ PIDL_ARGS="$PIDL_ARGS --uint-enums"
+fi
+
+dnl Figure out the flags to support named structure initializers
+
+LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_ERROR([c99 structure initializer are not supported])])
+
UNAME_S=`(uname -s) 2>/dev/null` || UNAME_S="unknown"
AC_MSG_CHECKING(uname -s)
AC_MSG_RESULT(${UNAME_S})
@@ -549,12 +562,10 @@ UNAME_P=`(uname -p) 2>/dev/null` || UNAME_P="unknown"
AC_MSG_CHECKING(uname -p)
AC_MSG_RESULT(${UNAME_P})
-AC_CANONICAL_SYSTEM
-
dnl Add #include for broken IRIX header files
case "$host_os" in
*irix6*)
- AC_ADD_INCLUDE(<standards.h>)
+ #TODO add to libreplace
if test x"$ac_cv_prog_gcc" != x"yes" ; then
dnl Fix sensible defaults for MIPSPro compilers. The
dnl error numbers are valid for the 7.3 compilers,
@@ -572,19 +583,18 @@ dnl Add #include for broken IRIX header files
;;
esac
-AC_VALIDATE_CACHE_SYSTEM_TYPE
-
DYNEXP=
+AC_SUBST(DYNEXP)
dnl Add modules that have to be built by default here
dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog 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_shutdown rpc_lsa_ds rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog rpc_echo auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default nss_info_template"
dnl These are preferably build shared, and static if dlopen() is not available
default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
if test "x$developer" = xyes; then
- default_static_modules="$default_static_modules rpc_echo"
+ default_static_modules="$default_static_modules rpc_rpcecho"
default_shared_modules="$default_shared_modules charset_weird"
fi
@@ -596,13 +606,6 @@ fi
case "$host_os" in
# Try to work out if this is the native HPUX compiler that uses the -Ae flag.
*hpux*)
-
- AC_PROG_CC_FLAG(Ae)
- # mmap on HPUX is completely broken...
- AC_DEFINE(MMAP_BLACKLIST, 1, [Whether MMAP is broken])
- if test $ac_cv_prog_cc_Ae = yes; then
- CPPFLAGS="$CPPFLAGS -Ae"
- fi
#
# Defines needed for HPUX support.
# HPUX has bigcrypt but (sometimes?) doesn't use it for
@@ -625,6 +628,7 @@ case "$host_os" in
AC_DEFINE(_LARGEFILE64_SOURCE, 1, [Whether to use large file support])
AC_DEFINE(_ALIGNMENT_REQUIRED, 1, [Required alignment])
AC_DEFINE(_MAX_ALIGNMENT, 4, [Maximum alignment])
+ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Unix 98 sources -- needed for socklen_t in getsockopt on HP/UX 11])
;;
esac
;;
@@ -806,21 +810,10 @@ main() {
#
*darwin*)
AC_DEFINE(BROKEN_UNICODE_COMPOSE_CHARACTERS, 1, [Does this system use unicode compose characters])
-# Add Fink directories for various packages, like dlcompat.
-# Note: iconv does that explicitly below, but other packages
-# don't.
- CPPFLAGS="$CPPFLAGS -I/sw/include"
- LDFLAGS="$LDFLAGS -L/sw/lib"
-
-# If we have dlsym_prepend_underscore (from Fink's dlcompat),
-# use that instead of plain dlsym.
-
- AC_CHECK_LIB(dl,dlopen)
- AC_CHECK_FUNCS(dlsym_prepend_underscore,[CPPFLAGS="$CPPFLAGS -Ddlsym=dlsym_prepend_underscore"])
# Add a system specific charset module.
-
default_shared_modules="$default_shared_modules charset_macosxfs"
+
;;
*hurd*)
AC_MSG_CHECKING([for LFS support])
@@ -846,11 +839,19 @@ exit(1);
esac
-AC_INLINE
-AC_HEADER_STDC
-AC_HEADER_DIRENT
-AC_HEADER_TIME
-AC_HEADER_SYS_WAIT
+AC_LIBREPLACE_BROKEN_CHECKS
+
+LIBREPLACE_DIR=`echo ${libreplacedir} | sed -e "s;${srcdir};;" -e "s;^/;;"`
+
+LIBREPLACE_OBJS=""
+for obj in ${LIBREPLACEOBJ}; do
+ LIBREPLACE_OBJS="${LIBREPLACE_OBJS} ${LIBREPLACE_DIR}/${obj}"
+done
+AC_SUBST(LIBREPLACE_OBJS)
+
+# add -ldl to the global LIBS
+LIBS="${LIBS} ${LIBDL}"
+
AC_CHECK_HEADERS(aio.h 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 memory.h alloca.h)
AC_CHECK_HEADERS(limits.h float.h)
@@ -860,9 +861,10 @@ AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h
AC_CHECK_HEADERS(sys/un.h)
AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
-AC_CHECK_HEADERS(sys/sysmacros.h security/_pam_macros.h dlfcn.h)
+AC_CHECK_HEADERS(sys/sysmacros.h)
AC_CHECK_HEADERS(sys/syslog.h syslog.h)
AC_CHECK_HEADERS(langinfo.h locale.h)
+AC_CHECK_HEADERS(xfs/libxfs.h)
AC_CHECK_HEADERS(rpcsvc/yp_prot.h,,,[[
#if HAVE_RPC_RPC_H
@@ -908,9 +910,8 @@ case "$host_os" in
fi
;;
esac
-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(shadow.h)
+AC_CHECK_HEADERS(nss.h nss_common.h nsswitch.h ns_api.h sys/security.h)
AC_CHECK_HEADERS(syscall.h sys/syscall.h)
AC_CHECK_HEADERS(sys/acl.h sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h)
@@ -918,30 +919,6 @@ AC_CHECK_HEADERS(sys/ea.h sys/proplist.h)
AC_CHECK_HEADERS(sys/cdefs.h glob.h)
-AC_CHECK_HEADERS(netinet/ip.h,,,[[
-#include <sys/types.h>
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#include <netinet/in.h>
-#if HAVE_NETINET_IN_SYSTM_H
-#include <netinet/in_systm.h>
-#endif
-]])
-
-AC_CHECK_HEADERS(net/if.h,,,[[
-#include <sys/types.h>
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-]])
-
-AC_CHECK_HEADERS(security/pam_modules.h,,,[[
-#if HAVE_SECURITY_PAM_APPL_H
-#include <security/pam_appl.h>
-#endif
-]])
-
# For experimental utmp support (lastlog on some BSD-like systems)
AC_CHECK_HEADERS(utmp.h utmpx.h lastlog.h)
@@ -968,6 +945,8 @@ AC_CHECK_TYPE(loff_t,off_t)
AC_CHECK_TYPE(offset_t,loff_t)
AC_CHECK_TYPE(ssize_t, int)
AC_CHECK_TYPE(wchar_t, unsigned short)
+AC_CHECK_TYPE(comparison_fn_t,
+[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
############################################
# for cups support we need libcups, and a handful of header files
@@ -1000,33 +979,7 @@ if test x$enable_iprint != xno; then
fi
############################################
-# we need dlopen/dlclose/dlsym/dlerror for PAM, the password database plugins and the plugin loading code
-AC_SEARCH_LIBS(dlopen, [dl])
-# dlopen/dlclose/dlsym/dlerror will be checked again later and defines will be set then
-
-############################################
-# check if the compiler can do immediate structures
-AC_CACHE_CHECK([for immediate structures],samba_cv_immediate_structures, [
- AC_TRY_COMPILE([
-#include <stdio.h>],
-[
- typedef struct {unsigned x;} FOOBAR;
- #define X_FOOBAR(x) ((FOOBAR) { x })
- #define FOO_ONE X_FOOBAR(1)
- FOOBAR f = FOO_ONE;
- static struct {
- FOOBAR y;
- } f2[] = {
- {FOO_ONE}
- };
-],
- samba_cv_immediate_structures=yes,samba_cv_immediate_structures=no)])
-if test x"$samba_cv_immediate_structures" = x"yes"; then
- AC_DEFINE(HAVE_IMMEDIATE_STRUCTURES,1,[Whether the compiler supports immediate structures])
-fi
-
-############################################
-# check if the compiler can do immediate structures
+# check if the compiler will optimize out function calls
AC_CACHE_CHECK([if the compiler will optimize out function calls],samba_cv_optimize_out_funcation_calls, [
AC_TRY_LINK([
#include <stdio.h>],
@@ -1105,9 +1058,6 @@ AC_CACHE_CHECK([for struct timespec type],samba_cv_struct_timespec, [
# include <time.h>
# endif
#endif
-#if HAVE_AIO_H
-#include <aio.h>
-#endif
],[struct timespec ts;],
samba_cv_struct_timespec=yes,samba_cv_struct_timespec=no)])
if test x"$samba_cv_struct_timespec" = x"yes"; then
@@ -1217,6 +1167,13 @@ AC_CHECK_LIB(readline, rl_completion_matches,
[],
[$TERMLIBS])
+# not all readline libs have rl_event_hook or history_list
+AC_CHECK_DECLS(rl_event_hook, [], [], [#include <readline/readline.h>])
+AC_CHECK_LIB(readline, history_list,
+ [AC_DEFINE(HAVE_HISTORY_LIST, 1, [Do we have history_list?])],
+ [],
+ [$TERMLIBS])
+
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
@@ -1262,7 +1219,8 @@ if test x"$ac_cv_func_execl" = x"no"; then
EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/smbrun\$(EXEEXT)"
fi
-AC_CHECK_FUNCS(dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64)
+AC_CHECK_FUNCS(waitpid getcwd strdup strndup strnlen strerror chown fchown chmod fchmod chroot link mknod mknod64)
+AC_CHECK_FUNCS(strtol strtoll strtoul strtoull strtouq __strtoull)
AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync memset strlcpy strlcat setpgid)
AC_CHECK_FUNCS(memmove vsnprintf snprintf asprintf vasprintf setsid glob strpbrk pipe crypt16 getauthuid)
AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent)
@@ -1271,12 +1229,14 @@ AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf mktime rename ftruncate
AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64)
AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf)
AC_CHECK_FUNCS(opendir64 readdir64 seekdir64 telldir64 rewinddir64 closedir64)
+AC_CHECK_FUNCS(getpwent_r)
AC_CHECK_FUNCS(getdents getdents64)
AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink)
AC_CHECK_FUNCS(syslog vsyslog timegm)
AC_CHECK_FUNCS(setlocale nl_langinfo)
AC_CHECK_FUNCS(nanosleep)
AC_CHECK_FUNCS(mlock munlock mlockall munlockall)
+AC_CHECK_FUNCS(memalign posix_memalign)
AC_CHECK_HEADERS(sys/mman.h)
# setbuffer, shmget, shm_open are needed for smbtorture
AC_CHECK_FUNCS(setbuffer shmget shm_open)
@@ -1286,6 +1246,20 @@ AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
AC_CHECK_FUNCS(backtrace_symbols)
AC_CHECK_LIB(exc, trace_back_stack)
+echo -n "checking for GPFS GPL libs... "
+save_LIBS="$LIBS"
+LIBS="$LIBS -lgpfs_gpl"
+AC_TRY_LINK([#include <gpfs_gpl.h>],
+ [gpfs_set_share(0,GPFS_SHARE_READ,GPFS_DENY_NONE)],
+ samba_cv_HAVE_GPFS=yes,
+ samba_cv_HAVE_GPFS=no)
+echo $samba_cv_HAVE_GPFS
+if test x"$samba_cv_HAVE_GPFS" = x"yes"; then
+ AC_DEFINE(HAVE_GPFS,1,[Whether GPFS GPL libs are available])
+ default_shared_modules="$default_shared_modules vfs_gpfs"
+fi
+LIBS="$save_LIBS"
+
# Note that all the libunwind symbols in the API are defined to internal
# platform-specific version, so we must include libunwind.h before checking
# any of them.
@@ -1370,9 +1344,6 @@ fi
AC_SUBST(LIBUNWIND_PTRACE)
-# syscall() is needed for smbwrapper.
-AC_CHECK_FUNCS(syscall)
-
AC_CHECK_FUNCS(_dup _dup2 _opendir _readdir _seekdir _telldir _closedir)
AC_CHECK_FUNCS(__dup __dup2 __opendir __readdir __seekdir __telldir __closedir)
AC_CHECK_FUNCS(__getcwd _getcwd)
@@ -1618,6 +1589,30 @@ case "$host_os" in
;;
esac
+########################################################
+# Do xattr functions take additional options like on Darwin?
+if test x"$ac_cv_func_getxattr" = x"yes" ; then
+ AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, [
+ old_LIBS=$LIBS
+ LIBS="$LIBS $ACL_LIBS"
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #if HAVE_ATTR_XATTR_H
+ #include <attr/xattr.h>
+ #elif HAVE_SYS_XATTR_H
+ #include <sys/xattr.h>
+ #endif
+ ],[
+ getxattr(0, 0, 0, 0, 0, 0);
+ ],
+ [smb_attr_cv_xattr_add_opt=yes],
+ [smb_attr_cv_xattr_add_opt=no;LIBS=$old_LIBS])
+ ])
+ if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then
+ AC_DEFINE(XATTR_ADD_OPT, 1, [xattr functions have additional options])
+ fi
+fi
+
# Check if we have extattr
case "$host_os" in
*freebsd4* | *dragonfly* )
@@ -1631,6 +1626,34 @@ case "$host_os" in
;;
esac
+# Set defaults
+PIE_CFLAGS=""
+PIE_LDFLAGS=""
+AC_ARG_ENABLE(pie, [ --enable-pie Turn on pie support if available (default=yes)])
+
+if test "x$enable_pie" != xno
+then
+ AC_CACHE_CHECK(for -pie and -fPIE, samba_cv_fpie,
+ [
+ cat > conftest.c <<EOF
+int foo;
+main () { return 0;}
+EOF
+ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -pie -fPIE -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD])
+ then
+ samba_cv_fpie=yes
+ else
+ samba_cv_fpie=no
+ fi
+ rm -f conftest*
+ ])
+ if test x"${samba_cv_fpie}" = x"yes"
+ then
+ PIE_CFLAGS="-fPIE"
+ PIE_LDFLAGS="-pie"
+ fi
+fi
+
# Assume non-shared by default and override below
BLDSHARED="false"
@@ -1639,13 +1662,11 @@ HOST_OS="$host_os"
LDSHFLAGS="-shared"
SONAMEFLAG="#"
SHLD="\${CC} \${CFLAGS}"
-PICFLAGS=""
-PICSUFFIX="po"
+PICFLAG="${PIE_CFLAGS}"
SHLIBEXT="so"
-if test "$enable_shared" = "yes"; then
- # this bit needs to be modified for each OS that is suported by
- # smbwrapper. You need to specify how to create a shared library and
+# this bit needs to be modified for each OS that supports share libs
+# You need to specify how to create a shared library and
# how to compile C code to produce PIC object files
AC_MSG_CHECKING([ability to build shared libraries])
@@ -1660,7 +1681,7 @@ if test "$enable_shared" = "yes"; then
LDSHFLAGS="-shared -Wl,-Bsymbolic"
fi
DYNEXP="-Wl,--export-dynamic"
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
SONAMEFLAG="-Wl,-soname="
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
;;
@@ -1669,17 +1690,16 @@ if test "$enable_shared" = "yes"; then
LDSHFLAGS="-G"
SONAMEFLAG="-h "
if test "${GCC}" = "yes"; then
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
SONAMEFLAG="-Wl,-soname="
if test "${ac_cv_prog_gnu_ld}" = "yes"; then
DYNEXP="-Wl,-E"
fi
else
- PICFLAGS="-KPIC"
+ PICFLAG="-KPIC"
## ${CFLAGS} added for building 64-bit shared
## libs using Sun's Compiler
LDSHFLAGS="-G \${CFLAGS}"
- PICSUFFIX="po.o"
fi
AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block])
AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly])
@@ -1688,7 +1708,7 @@ if test "$enable_shared" = "yes"; then
BLDSHARED="true"
LDSHFLAGS="-G"
SONAMEFLAG="-Wl,-h,"
- PICFLAGS="-KPIC" # Is this correct for SunOS
+ PICFLAG="-KPIC" # Is this correct for SunOS
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly])
;;
@@ -1697,7 +1717,7 @@ if test "$enable_shared" = "yes"; then
LDSHFLAGS="-shared"
DYNEXP="-Wl,--export-dynamic"
SONAMEFLAG="-Wl,-soname,"
- PICFLAGS="-fPIC -DPIC"
+ PICFLAG="-fPIC -DPIC"
AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block])
AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly])
;;
@@ -1705,7 +1725,7 @@ if test "$enable_shared" = "yes"; then
LDSHFLAGS="-shared"
DYNEXP="-Wl,-Bdynamic"
SONAMEFLAG="-Wl,-soname,"
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block])
AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly])
;;
@@ -1719,20 +1739,19 @@ if test "$enable_shared" = "yes"; then
SONAMEFLAG="-soname "
SHLD="\${LD}"
if test "${GCC}" = "yes"; then
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
else
- PICFLAGS="-KPIC"
+ PICFLAG="-KPIC"
fi
AC_DEFINE(STAT_ST_BLOCKSIZE,512,[The size of a block])
;;
*aix*) AC_DEFINE(AIX,1,[Whether the host os is aix])
BLDSHARED="true"
- LDSHFLAGS="-Wl,-G,-bexpall"
+ LDSHFLAGS="-Wl,-G,-bexpall,-bbigtoc"
DYNEXP="-Wl,-brtl,-bexpall,-bbigtoc"
- PICFLAGS="-O2"
+ PICFLAG="-O2"
# as AIX code is always position independent...
- # .po will just create compile warnings, use .o:
- PICSUFFIX="o"
+ # .po will just create compile warnings, use po.o:
if test "${GCC}" != "yes"; then
## for funky AIX compiler using strncpy()
CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
@@ -1749,9 +1768,9 @@ if test "$enable_shared" = "yes"; then
SHLD="cc"
LDSHFLAGS="-b -Wl,-B,symbolic,-b,-z"
SONAMEFLAG="-Wl,+h "
- PICFLAGS="+z"
+ PICFLAG="+z"
elif test "${GCC}" = "yes"; then
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
fi
if test "$host_cpu" = "ia64"; then
SHLIBEXT="so"
@@ -1770,7 +1789,7 @@ if test "$enable_shared" = "yes"; then
BLDSHARED="true"
LDSHFLAGS="-shared"
SONAMEFLAG="-Wl,-soname,"
- PICFLAGS="-fPIC"
+ PICFLAG="-fPIC"
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
AC_DEFINE(BROKEN_GETGRNAM,1,[Does getgrnam work correctly])
;;
@@ -1781,7 +1800,7 @@ if test "$enable_shared" = "yes"; then
BLDSHARED="true"
LDSHFLAGS="-shared"
SONAMEFLAG="-Wl,-soname,"
- PICFLAGS="-KPIC"
+ PICFLAG="-KPIC"
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
;;
*next2*) AC_DEFINE(NEXT2,1,[Whether the host os is NeXT v2])
@@ -1826,34 +1845,70 @@ if test "$enable_shared" = "yes"; then
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
;;
esac
- AC_SUBST(DYNEXP)
- AC_MSG_RESULT($BLDSHARED)
- AC_MSG_CHECKING([linker flags for shared libraries])
- AC_MSG_RESULT([$LDSHFLAGS])
- AC_MSG_CHECKING([compiler flags for position-independent code])
- AC_MSG_RESULT([$PICFLAGS])
+
+if test "$enable_shared" != "yes"; then
+ BLDSHARED=false
fi
+ AC_MSG_RESULT($BLDSHARED)
+
+AC_MSG_CHECKING([LDFLAGS])
+AC_MSG_RESULT([$LDFLAGS])
+AC_MSG_CHECKING([DYNEXP])
+AC_MSG_RESULT([$DYNEXP])
+
#######################################################
# test whether building a shared library actually works
if test $BLDSHARED = true; then
+
+AC_MSG_CHECKING([SHLD])
+AC_MSG_RESULT([$SHLD])
+AC_MSG_CHECKING([LDSHFLAGS])
+AC_MSG_RESULT([$LDSHFLAGS])
+
+AC_MSG_CHECKING([SHLIBEXT])
+AC_MSG_RESULT([$SHLIBEXT])
+AC_MSG_CHECKING([SONAMEFLAG])
+AC_MSG_RESULT([$SONAMEFLAG])
+
+AC_MSG_CHECKING([PICFLAG])
+AC_MSG_RESULT([$PICFLAG])
+
+AC_MSG_CHECKING([NSSSONAMEVERSIONSUFFIX])
+AC_MSG_RESULT([$NSSSONAMEVERSIONSUFFIX])
+
AC_CACHE_CHECK([whether building shared libraries actually works],
[ac_cv_shlib_works],[
# try building a trivial shared library
ac_cv_shlib_works=no
# The $SHLD and $LDSHFLAGS variables may contain references to other
# variables so they need to be eval'ed.
- $CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o \
- shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c && \
+ $CC $CPPFLAGS $CFLAGS $PICFLAG -c -o \
+ shlib.o ${srcdir-.}/tests/shlib.c && \
`eval echo $SHLD` `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \
- shlib.$PICSUFFIX && ac_cv_shlib_works=yes
- rm -f "shlib.$SHLIBEXT" shlib.$PICSUFFIX
+ shlib.o && ac_cv_shlib_works=yes
+ rm -f "shlib.$SHLIBEXT" shlib.o
+
])
if test $ac_cv_shlib_works = no; then
BLDSHARED=false
fi
fi
+if test x"$BLDSHARED" != x"true"; then
+ LDSHFLAGS="shared-libraries-disabled"
+ SONAMEFLAG="shared-libraries-disabled"
+ NSSSONAMEVERSIONSUFFIX="shared-libraries-disabled"
+ SHLD="shared-libraries-disabled"
+ PICFLAG="${PIE_CFLAGS}"
+ SHLIBEXT="shared_libraries_disabled"
+fi
+
+AC_MSG_CHECKING([used PICFLAG])
+AC_MSG_RESULT([$PICFLAG])
+
+AC_DEFINE_UNQUOTED(SHLIBEXT, "$SHLIBEXT", [Shared library extension])
+
################
AC_CACHE_CHECK([for long long],samba_cv_have_longlong,[
@@ -2068,16 +2123,12 @@ if test x"$samba_cv_WITH_PROFILE" = x"yes"; then
AC_LIBTESTFUNC(rt, clock_gettime,
[
- SMB_IS_LIBPTHREAD_LINKED(
- [ SMB_REMOVELIB(rt) ],
- [
AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
[Whether clock_gettime is available])
SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC)
SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID)
SMB_CHECK_CLOCK_ID(CLOCK_REALTIME)
])
- ])
fi
@@ -2459,36 +2510,56 @@ if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then
AC_DEFINE(HAVE_KERNEL_CHANGE_NOTIFY,1,[Whether kernel notifies changes])
fi
+AC_CACHE_CHECK([for inotify support],samba_cv_HAVE_INOTIFY,[
+AC_CHECK_HEADERS(linux/inotify.h asm/unistd.h)
+AC_CHECK_FUNC(inotify_init)
+AC_HAVE_DECL(__NR_inotify_init, [#include <asm/unistd.h>])
+],
+samba_cv_HAVE_INOTIFY=yes,
+samba_cv_HAVE_INOTIFY=no,
+samba_cv_HAVE_INOTIFY=cross)
+
+if test x"$ac_cv_func_inotify_init" = x"yes" -a x"$ac_cv_header_linux_inotify_h" = x"yes"; then
+ AC_DEFINE(HAVE_INOTIFY,1,[Whether kernel has inotify support])
+fi
+
#################################################
# Check if FAM notifications are available. For FAM info, see
# http://oss.sgi.com/projects/fam/
# http://savannah.nongnu.org/projects/fam/
+AC_ARG_ENABLE(fam,
+[ --enable-fam Turn on FAM support (default=auto)])
+
+if test x$enable_fam != xno; then
+ AC_CHECK_HEADERS(fam.h, [samba_cv_HAVE_FAM_H=yes], [samba_cv_HAVE_FAM_H=no])
+ if test x"$samba_cv_HAVE_FAM_H" = x"yes"; then
+ # On IRIX, libfam requires libC, but other FAM implementations
+ # might not need it.
+ AC_CHECK_LIB(fam, FAMOpen2,
+ [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam"],
+ [samba_cv_HAVE_LIBFAM=no])
+
+ if test x"$samba_cv_HAVE_LIBFAM" = x"no" ; then
+ samba_fam_xtra=-lC
+ AC_CHECK_LIB_EXT(fam, samba_fam_xtra, FAMOpen2,
+ [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam -lC"],
+ [samba_cv_HAVE_LIBFAM=no])
+ unset samba_fam_xtra
+ fi
+ fi
-AC_CHECK_HEADERS(fam.h, [samba_cv_HAVE_FAM_H=yes], [samba_cv_HAVE_FAM_H=no])
-if test x"$samba_cv_HAVE_FAM_H" = x"yes"; then
- # On IRIX, libfam requires libC, but other FAM implementations might not
- # need it.
- AC_CHECK_LIB(fam, FAMOpen2,
- [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam"],
- [samba_cv_HAVE_LIBFAM=no])
-
- if test x"$samba_cv_HAVE_LIBFAM" = x"no" ; then
- samba_fam_xtra=-lC
- AC_CHECK_LIB_EXT(fam, samba_fam_xtra, FAMOpen2,
- [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam -lC"],
- [samba_cv_HAVE_LIBFAM=no])
- unset samba_fam_xtra
+ if test x"$samba_cv_HAVE_LIBFAM" = x"yes" ; then
+ default_shared_modules="$default_shared_modules vfs_notify_fam"
+ AC_TRY_COMPILE([#include <fam.h>],
+ [FAMCodes code = FAMChanged;],
+ AC_DEFINE(HAVE_FAM_H_FAMCODES_TYPEDEF, 1,
+ [Whether fam.h contains a typedef for enum FAMCodes]),
+ [])
fi
-fi
-if test x"$samba_cv_HAVE_LIBFAM" = x"yes" ; then
- AC_DEFINE(HAVE_FAM_CHANGE_NOTIFY, 1,
- [Whether FAM is file notifications are available])
- AC_TRY_COMPILE([#include <fam.h>],
- [FAMCodes code = FAMChanged;],
- AC_DEFINE(HAVE_FAM_H_FAMCODES_TYPEDEF, 1,
- [Whether fam.h contains a typedef for enum FAMCodes]),
- [])
+ if test x$enable_fam = xyes && test x"$samba_cv_HAVE_LIBFAM" != xyes ; then
+ AC_MSG_ERROR(FAM support requested but FAM library not available )
+ fi
fi
#################################################
@@ -2668,40 +2739,6 @@ if test x"$samba_cv_HAVE_BROKEN_GETGROUPS" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_GETGROUPS,1,[Whether getgroups is broken])
fi
-AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[
-SAVE_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt"
-AC_TRY_COMPILE([
-#define REPLACE_GETPASS 1
-#define NO_PROTO_H 1
-#define NO_CONFIG_H 1
-#define main dont_declare_main
-#include "${srcdir-.}/lib/getsmbpass.c"
-#undef main
-],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no)
-CPPFLAGS="$SAVE_CPPFLAGS"
-])
-if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then
- AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced])
-fi
-
-AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[
-AC_TRY_RUN([
-#include <stdio.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-main() { struct in_addr ip; ip.s_addr = 0x12345678;
-if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
- strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
-exit(1);}],
- samba_cv_REPLACE_INET_NTOA=yes,samba_cv_REPLACE_INET_NTOA=no,samba_cv_REPLACE_INET_NTOA=cross)])
-if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then
- AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced])
-fi
-
AC_CACHE_CHECK([for secure mkstemp],samba_cv_HAVE_SECURE_MKSTEMP,[
AC_TRY_RUN([#include <stdlib.h>
#include <sys/types.h>
@@ -2746,38 +2783,35 @@ SMB_CHECK_SYSCONF(_SC_NGROUPS_MAX)
SMB_CHECK_SYSCONF(_SC_NPROC_ONLN)
SMB_CHECK_SYSCONF(_SC_NPROCESSORS_ONLN)
SMB_CHECK_SYSCONF(_SC_PAGESIZE)
-
-AC_CACHE_CHECK([for root],samba_cv_HAVE_ROOT,[
-AC_TRY_RUN([main() { exit(getuid() != 0); }],
- samba_cv_HAVE_ROOT=yes,samba_cv_HAVE_ROOT=no,samba_cv_HAVE_ROOT=cross)])
-if test x"$samba_cv_HAVE_ROOT" = x"yes"; then
- AC_DEFINE(HAVE_ROOT,1,[Whether current user is root])
-else
- AC_MSG_WARN(running as non-root will disable some tests)
-fi
+AC_CHECK_FUNCS(getpagesize)
##################
# look for a method of finding the list of network interfaces
iface=no;
AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_RUN([
#define HAVE_IFACE_AIX 1
#define AUTOCONF_TEST 1
-#include "confdefs.h"
+#undef _XOPEN_SOURCE_EXTENDED
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)])
+CPPFLAGS="$SAVE_CPPFLAGS"
if test x"$samba_cv_HAVE_IFACE_AIX" = x"yes"; then
iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available])
fi
if test $iface = no; then
AC_CACHE_CHECK([for iface ifconf],samba_cv_HAVE_IFACE_IFCONF,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_RUN([
#define HAVE_IFACE_IFCONF 1
#define AUTOCONF_TEST 1
-#include "confdefs.h"
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)])
+CPPFLAGS="$SAVE_CPPFLAGS"
if test x"$samba_cv_HAVE_IFACE_IFCONF" = x"yes"; then
iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available])
fi
@@ -2785,12 +2819,14 @@ fi
if test $iface = no; then
AC_CACHE_CHECK([for iface ifreq],samba_cv_HAVE_IFACE_IFREQ,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_RUN([
#define HAVE_IFACE_IFREQ 1
#define AUTOCONF_TEST 1
-#include "confdefs.h"
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)])
+CPPFLAGS="$SAVE_CPPFLAGS"
if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available])
fi
@@ -2976,47 +3012,6 @@ if test x"$samba_cv_REALPATH_TAKES_NULL" = x"yes"; then
fi
#################################################
-# check for smbwrapper support
-AC_MSG_CHECKING(whether to use smbwrapper)
-AC_ARG_WITH(smbwrapper,
-[ --with-smbwrapper Include SMB wrapper support (default=no) ],
-[ case "$withval" in
- yes)
- AC_MSG_RESULT(yes)
- AC_DEFINE(WITH_SMBWRAPPER,1,[Whether to include smbwrapper support])
- WRAPPROG="bin/smbsh\$(EXEEXT)"
- WRAP="bin/smbwrapper.$SHLIBEXT"
- WRAP_OBJS="\$(SMBW_OBJ1) \$(SMBWRAPPER_OBJ1)"
- WRAP_INC="-I\$(srcdir)/smbwrapper"
-
-# Conditions under which smbwrapper should not be built.
-
- if test x"$PICFLAGS" = x; then
- echo No support for PIC code - disabling smbwrapper and smbsh
- WRAPPROG=""
- WRAP=""
- WRAP_OBJS=""
- WRAP_INC=""
- elif test x$ac_cv_func_syscall = xno; then
- AC_MSG_RESULT([No syscall() -- disabling smbwrapper and smbsh])
- WRAPPROG=""
- WRAP=""
- WRAP_OBJS=""
- WRAP_INC=""
- fi
- EXTRA_ALL_TARGETS="$EXTRA_ALL_TARGETS $WRAPPROG $WRAP"
- SMBWRAPPER="$WRAPPROG $WRAP"
- SMBWRAP_OBJS="$WRAP_OBJS"
- SMBWRAP_INC="$WRAP_INC"
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
- esac ],
- AC_MSG_RESULT(no)
-)
-
-#################################################
# check for AFS clear-text auth support
samba_cv_WITH_AFS=no
AC_MSG_CHECKING(whether to use AFS clear-text auth)
@@ -3089,7 +3084,7 @@ fi
#################################################
# check whether to compile AFS/NT ACL mapping module
samba_cv_WITH_VFS_AFSACL=no
-AC_MSG_CHECKING(whether to use AFS fake-kaserver)
+AC_MSG_CHECKING(whether to use AFS ACL mapping module)
AC_ARG_WITH(vfs-afsacl,
[ --with-vfs-afsacl Include AFS to NT ACL mapping module (default=no) ],
[ case "$withval" in
@@ -3149,6 +3144,9 @@ SMBLDAP=""
AC_SUBST(SMBLDAP)
SMBLDAPUTIL=""
AC_SUBST(SMBLDAPUTIL)
+LDBLDAP=""
+AC_SUBST(LDBLDAP)
+
if test x"$with_ldap_support" != x"no"; then
##################################################################
@@ -3165,6 +3163,18 @@ if test x"$with_ldap_support" != x"no"; then
with_ldap_support=no
fi
+
+ ##################################################################
+ # HP/UX does not have ber_tag_t, disable LDAP there
+ AC_CHECK_TYPE(ber_tag_t,,,[#include <lber.h>])
+ if test x"$ac_cv_type_ber_tag_t" != x"yes"; then
+ if test x"$with_ldap_support" = x"yes"; then
+ AC_MSG_ERROR(ber_tag_t is needed for LDAP support)
+ else
+ AC_MSG_WARN(ber_tag_t is needed for LDAP support)
+ fi
+ with_ldap_support=no
+ fi
fi
if test x"$with_ldap_support" != x"no"; then
@@ -3197,7 +3207,7 @@ if test x"$with_ldap_support" != x"no"; then
AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc])
- AC_CHECK_FUNC_EXT(ldap_dn2ad_canonical,$LDAP_LIBS)
+ AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes"; then
AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
@@ -3406,8 +3416,10 @@ if test x"$with_ads_support" != x"no"; then
fi
# Now we have determined whether we really want ADS support
-
+use_ads=no
if test x"$with_ads_support" != x"no"; then
+ use_ads=yes
+ have_gssapi=no
ac_save_LIBS=$LIBS
# now check for gssapi headers. This is also done here to allow for
@@ -3425,8 +3437,7 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_LIB_EXT(roken, KRB5_LIBS, roken_getaddrinfo_hostspec)
# Heimdal checks. On static Heimdal gssapi must be linked before krb5.
- AC_CHECK_LIB_EXT(gssapi, KRB5_LIBS, gss_display_status,[],[],
- AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available]))
+ AC_CHECK_LIB_EXT(gssapi, KRB5_LIBS, gss_display_status,[],[],have_gssapi=yes)
########################################################
# now see if we can find the krb5 libs in standard paths
@@ -3436,11 +3447,13 @@ if test x"$with_ads_support" != x"no"; then
########################################################
# now see if we can find the gssapi libs in standard paths
- AC_CHECK_LIB_EXT(gssapi_krb5, KRB5_LIBS,gss_display_status,[],[],
- AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available]))
+ if test x"$have_gssapi" != x"yes"; then
+ AC_CHECK_LIB_EXT(gssapi_krb5, KRB5_LIBS,gss_display_status,[],[],have_gssapi=yes)
+ fi
AC_CHECK_FUNC_EXT(krb5_set_real_time, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_set_default_in_tkt_etypes, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_set_default_tgs_enctypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_set_default_tgs_ktypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal2salt, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_use_enctype, $KRB5_LIBS)
@@ -3452,20 +3465,18 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_locate_kdc, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS)
- AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_unparsed_name, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_keytab_entry_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_kt_free_entry, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_krbhst_init, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_c_enctype_compare, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_enctypes_compatible_keys, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_crypto_init, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_crypto_destroy, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_decode_ap_req, $KRB5_LIBS)
- AC_CHECK_FUNC_EXT(decode_krb5_ap_req, $KRB5_LIBS)
- AC_CHECK_FUNC_EXT(krb5_free_ap_req, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(free_AP_REQ, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_c_verify_checksum, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS)
@@ -3475,9 +3486,36 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_get_renewed_creds, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_kdc_cred, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_error_contents, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(initialize_krb5_error_table, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_alloc, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_free, $KRB5_LIBS)
LIBS="$KRB5_LIBS $LIBS"
+ AC_CACHE_CHECK(whether krb5_ticket contains kvno and enctype,
+ smb_krb5_ticket_has_keyinfo,
+ [
+ AC_TRY_COMPILE(
+ [
+ #include <krb5.h>
+ ],
+ [
+ krb5_ticket ticket;
+ krb5_kvno kvno;
+ krb5_enctype enctype;
+
+ enctype = ticket.enc_part.enctype;
+ kvno = ticket.enc_part.kvno;
+ ],
+ [ smb_krb5_ticket_has_keyinfo=yes ],
+ [ smb_krb5_ticket_has_keyinfo=no ])
+ ])
+
+ if test x"$smb_krb5_ticket_has_keyinfo" = x"yes" ; then
+ AC_DEFINE(KRB5_TICKET_HAS_KEYINFO, 1,
+ [Whether the krb5_ticket structure contains the kvno and enctype])
+ fi
+
AC_CACHE_CHECK(whether krb5_verify_checksum takes 7 arguments, smb_krb5_verify_checksum, [
AC_TRY_COMPILE([
#include <krb5.h>],
@@ -3747,21 +3785,6 @@ if test x"$with_ads_support" != x"no"; then
[Whether the krb5_address struct has a magic property])
fi
- if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then
- AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
- AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
- AC_MSG_CHECKING(whether Active Directory and krb5 support is used)
- AC_MSG_RESULT(yes)
- else
- if test x"$with_ads_support" = x"yes"; then
- AC_MSG_ERROR(libkrb5 is needed for Active Directory support)
- else
- AC_MSG_WARN(libkrb5 is needed for Active Directory support)
- fi
- KRB5_LIBS=""
- with_ads_support=no
- fi
-
AC_CACHE_CHECK([for WRFILE: keytab support],
samba_cv_HAVE_WRFILE_KEYTAB,[
AC_TRY_RUN([
@@ -3809,12 +3832,163 @@ if test x"$with_ads_support" != x"no"; then
[Whether the type krb5_addresses type exists])
fi
+ #
+ #
+ # Now the decisions whether we can support krb5
+ #
+ # NOTE: all tests should be done before this block!
+ #
+ #
+ if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" != x"yes"; then
+ AC_MSG_WARN(krb5_mk_req_extended not found in -lkrb5)
+ use_ads=no
+ fi
+
+ if test x"$ac_cv_func_ext_krb5_principal2salt" != x"yes" -a \
+ x"$ac_cv_func_ext_krb5_get_pw_salt" != x"yes"
+ then
+ AC_MSG_WARN(no CREATE_KEY_FUNCTIONS detected)
+ use_ads=no
+ fi
+
+ if test x"$ac_cv_func_ext_krb5_get_permitted_enctypes" != x"yes" -a \
+ x"$ac_cv_func_ext_krb5_get_default_in_tkt_etypes" != x"yes"
+ then
+ AC_MSG_WARN(no GET_ENCTYPES_FUNCTIONS detected)
+ use_ads=no
+ fi
+
+ if test x"$ac_cv_func_ext_krb5_kt_free_entry" != x"yes" -a \
+ x"$ac_cv_func_ext_krb5_free_keytab_entry_contents" != x"yes"
+ then
+ AC_MSG_WARN(no KT_FREE_FUNCTION detected)
+ use_ads=no
+ fi
+
+ if test x"$ac_cv_func_ext_krb5_c_verify_checksum" != x"yes" -a \
+ x"$ac_cv_func_ext_krb5_verify_checksum" != x"yes"
+ then
+ AC_MSG_WARN(no KRB5_VERIFY_CHECKSUM_FUNCTION detected)
+ use_ads=no
+ fi
+
+ if test x"$smb_krb5_ticket_has_keyinfo" != x"yes" ; then
+
+ # We only need the following functions if we can't get the enctype
+ # and kvno out of the ticket directly (ie. on Heimdal).
+
+ if test x"$ac_cv_func_ext_free_AP_REQ" != x"yes"
+ then
+ AC_MSG_WARN(no KRB5_AP_REQ_FREE_FUNCTION detected)
+ use_ads=no
+ fi
+
+ if test x"$ac_cv_func_ext_krb5_decode_ap_req" != x"yes"
+ then
+ AC_MSG_WARN(no KRB5_AP_REQ_DECODING_FUNCTION detected)
+ use_ads=no
+ fi
+
+ fi
+
+ if test x"$use_ads" = x"yes"; then
+ AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
+ AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
+ if test x"$have_gssapi" = x"yes"; then
+ AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])
+ fi
+ else
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(krb5 libs don't have all features required for Active Directory support)
+ else
+ AC_MSG_WARN(krb5 libs don't have all features required for Active Directory support)
+ fi
+ AC_REMOVE_DEFINE(HAVE_KRB5_H)
+ AC_REMOVE_DEFINE(HAVE_GSSAPI_H)
+ AC_REMOVE_DEFINE(HAVE_GSSAPI_GSSAPI_GENERIC_H)
+ AC_REMOVE_DEFINE(HAVE_GSSAPI_GSSAPI_H)
+ KRB5_LIBS=""
+ with_ads_support=no
+ fi
+ AC_MSG_CHECKING(whether Active Directory and krb5 support is used)
+ AC_MSG_RESULT([$use_ads])
+
LIBS="$ac_save_LIBS"
fi
AC_CHECK_LIB_EXT(nscd, NSCD_LIBS, nscd_flush_cache)
PASSDB_LIBS="$PASSDB_LIBS $NSCD_LIBS"
+
+########################################################
+# Compile with DNS Updates support?
+
+with_dnsupdate_support=no
+AC_MSG_CHECKING([whether to enable DNS Updates support])
+
+AC_ARG_WITH(dnsupdate,
+[ --with-dnsupdate Enable DNS Updates support (default no)],
+[ case "$withval" in
+ yes|no)
+ with_dnsupdate_support=$withval
+ ;;
+ esac ])
+
+AC_MSG_RESULT($with_dnsupdate_support)
+
+if test x"$with_dnsupdate_support" != x"no"; then
+
+ ################################################################
+ # first test for Active Directory support being enabled
+ #if test x"$with_ads_support" = x"no"; then
+ # AC_MSG_ERROR(Active Directory support is required to enable DNS Update support)
+ # with_dnsupdate_support=no
+ #fi
+ ##################################################################
+ # then test for uuid.h (necessary to generate unique DNS keynames
+ # (uuid.h is required for this test)
+ AC_CHECK_HEADERS(uuid/uuid.h)
+
+ if test x"$ac_cv_header_uuid_uuid_h" != x"yes"; then
+ if test x"$with_dnsupdate_support" = x"yes"; then
+ AC_MSG_ERROR(uuid.h is needed to enable DNS Updates support)
+ else
+ AC_MSG_WARN(uuid.h is needed to enable DNS Updates support)
+ fi
+ with_dnsupdate_support=no
+ fi
+fi
+
+if test x"$with_dnsupdate_support" != x"no"; then
+
+ ########################################################
+ # Now see if we can find the uuid libs in standard paths
+ # On some systems, the uuid API is in libc, so we have to
+ # be careful not to insert a spurious -luuid.
+
+ UUID_LIBS=""
+ AC_LIBTESTFUNC(uuid, uuid_generate,
+ [
+ case " $LIBS " in
+ *\ -luuid\ *)
+ UUID_LIBS="-luuid"
+ SMB_REMOVE_LIB(uuid)
+ ;;
+ esac
+
+ with_dnsupdate_support=yes
+ AC_DEFINE(WITH_DNS_UPDATES,1,[Whether to enable DNS Update support])
+ ],
+ [
+ if test x"$with_dnsupdate_support" = x"yes"; then
+ AC_MSG_ERROR(libuuid is needed to enable DNS Updates support)
+ else
+ AC_MSG_WARN(libuuid is needed to enable DNS Updates support)
+ fi
+ with_dnsupdate_support=no
+ ])
+fi
+
#################################################
# check for automount support
AC_MSG_CHECKING(whether to use automount)
@@ -3902,32 +4076,76 @@ AC_ARG_WITH(cifsmount,
#################################################
# check for a PAM clear-text auth, accounts, password and session support
with_pam_for_crypt=no
-AC_MSG_CHECKING(whether to use PAM)
+try_pam=no
+AC_MSG_CHECKING(whether to try PAM support)
AC_ARG_WITH(pam,
[ --with-pam Include PAM support (default=no)],
[ case "$withval" in
- yes)
- AC_MSG_RESULT(yes)
- if test x"$ac_cv_header_security_pam_appl_h" = x"no"; then
+ yes|no)
+ try_pam=$withval
+ ;;
+ esac
+])
+AC_MSG_RESULT([$try_pam])
+
+use_pam=no
+create_pam_modules=no
+if test x"${try_pam}" != x"no";then
+ use_pam=yes
+ create_pam_modules=yes
+
+ AC_CHECK_HEADERS(security/pam_appl.h)
+ if test x"$ac_cv_header_security_pam_appl_h" != x"yes"; then
+ if test x"${try_pam}" = x"yes";then
+ AC_MSG_ERROR([--with-pam=yes but security/pam_appl.h not found])
+ fi
+ use_pam=no
+ create_pam_modules=no
+ fi
+
+ AC_CHECK_LIB_EXT(pam, PAM_LIBS, pam_get_data)
+ if test x"$ac_cv_lib_ext_pam_pam_get_data" != x"yes"; then
+ if test x"${try_pam}" = x"yes";then
+ AC_MSG_ERROR([--with-pam=yes but libpam not found])
+ fi
+ use_pam=no
+ create_pam_modules=no
+ fi
+
+ AC_CHECK_HEADERS(security/pam_modules.h,,,[[
+ #if HAVE_SECURITY_PAM_APPL_H
+ #include <security/pam_appl.h>
+ #endif
+ ]])
if test x"$ac_cv_header_security_pam_modules_h" = x"no"; then
- if test x"$ac_cv_header_security__pam_macros_h" = x"no"; then
- AC_MSG_ERROR(--with-pam specified but no PAM headers found)
- fi
+ if test x"${try_pam}" = x"yes";then
+ AC_MSG_ERROR([--with-pam=yes but security/pam_modules.h not found])
fi
+ create_pam_modules=no
fi
+
+ if test x"$use_pam" = x"yes"; then
AC_DEFINE(WITH_PAM,1,[Whether to include PAM support])
- AUTH_LIBS="$AUTH_LIBS -lpam"
+ AC_DEFINE(HAVE_LIBPAM,1,[Whether libpam is available])
+ AUTH_LIBS="$AUTH_LIBS $PAM_LIBS"
with_pam_for_crypt=yes
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
- esac ],
- AC_MSG_RESULT(no)
-)
-# we can't build a pam module if we don't have pam.
-AC_CHECK_LIB(pam, pam_get_data, [AC_DEFINE(HAVE_LIBPAM,1,[Whether libpam is available])])
+ if test x"$create_pam_modules" = x"yes"; then
+ AC_DEFINE(WITH_PAM_MODULES,1,[Whether to include PAM MODULES support])
+ # this checks are optional,
+ # we don't care about the results here
+ AC_CHECK_HEADERS(security/pam_ext.h security/_pam_macros.h)
+ AC_CHECK_FUNC_EXT(pam_vsyslog,$PAM_LIBS)
+ else
+ AC_MSG_WARN([PAM support detected but PAM MODULES support is missing])
+ fi
+ fi
+ AC_MSG_CHECKING(whether to use PAM support)
+ AC_MSG_RESULT([$use_pam])
+
+ AC_MSG_CHECKING(whether to have PAM MODULES support)
+ AC_MSG_RESULT([$create_pam_modules])
+fi # try_pam != no
#################################################
# check for pam_smbpass support
@@ -3943,14 +4161,11 @@ AC_ARG_WITH(pam_smbpass,
# Conditions under which pam_smbpass should not be built.
- if test x"$PICFLAGS" = x; then
- AC_MSG_ERROR([No support for PIC code])
- elif test x"$ac_cv_header_security_pam_appl_h" = x"no"; then
- AC_MSG_ERROR([No security/pam_appl.h found])
- elif test x$ac_cv_lib_pam_pam_get_data = xno; then
- AC_MSG_ERROR([No libpam found])
+ if test x"$BLDSHARED" != x"true"; then
+ AC_MSG_ERROR([No support for shared modules])
+ elif test x"$create_pam_modules" != x"yes"; then
+ AC_MSG_ERROR([No support for PAM MODULES])
else
- AUTH_LIBS="$AUTH_LIBS -lpam"
PAM_MODULES="pam_smbpass"
INSTALL_PAM_MODULES="installpammodules"
UNINSTALL_PAM_MODULES="uninstallpammodules"
@@ -4262,7 +4477,7 @@ fi
if test x"$samba_cv_SYSQUOTA_FOUND" != x"no"; then
AC_CACHE_CHECK([whether the sys_quota interface works],samba_cv_SYSQUOTA_WORKS,[
SAVE_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/nsswitch"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_COMPILE([
#include "confdefs.h"
#define NO_PROTO_H 1
@@ -4289,7 +4504,7 @@ fi
if test x"$samba_cv_SYSQUOTA_FOUND" != x"no" -a x"$samba_cv_found_xfs_header" = x"yes"; then
AC_CACHE_CHECK([whether the sys_quota interface works with XFS],samba_cv_SYSQUOTA_WORKS_XFS,[
SAVE_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/nsswitch"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_COMPILE([
#include "confdefs.h"
#define NO_PROTO_H 1
@@ -4309,7 +4524,7 @@ fi
AC_CACHE_CHECK([whether the old quota support works],samba_cv_QUOTA_WORKS,[
SAVE_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/nsswitch -I${srcdir-.}/smbwrapper"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
AC_TRY_COMPILE([
#include "confdefs.h"
#define NO_PROTO_H 1
@@ -4430,6 +4645,53 @@ AC_ARG_WITH(libmsrpc,
UNINSTALL_LIBMSRPC=uninstalllibmsrpc
)
+
+#################################################
+# should we build libaddns?
+INSTALL_LIBADDNS=
+UNINSTALL_LIBADDNS=
+LIBADDNS_SHARED=
+LIBADDNS=
+AC_MSG_CHECKING(whether to build the libaddns shared library)
+AC_ARG_WITH(libaddns,
+[ --with-libaddns Build the libaddns shared library (default=yes if shared libs supported)],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ if test $BLDSHARED = true; then
+ LIBADDNS_SHARED=bin/libaddns.$SHLIBEXT
+ LIBADDNS=libaddns
+ AC_MSG_RESULT(yes)
+ else
+ enable_static=yes
+ AC_MSG_RESULT(no shared library support -- will supply static library)
+ fi
+ if test $enable_static = yes; then
+ LIBADDNS=libaddns
+ fi
+ INSTALL_LIBADDNS=installlibaddns
+ UNINSTALL_LIBADDNS=uninstalllibaddns
+ ;;
+ esac ],
+[
+# if unspecified, default is to built it if possible.
+ if test $BLDSHARED = true; then
+ LIBADDNS_SHARED=bin/libaddns.$SHLIBEXT
+ LIBADDNS=libaddns
+ AC_MSG_RESULT(yes)
+ else
+ enable_static=yes
+ AC_MSG_RESULT(no shared library support -- will supply static library)
+ fi
+ if test $enable_static = yes; then
+ LIBADDNS=libaddns
+ fi]
+ INSTALL_LIBADDNS=installlibaddns
+ UNINSTALL_LIBADDNS=uninstalllibaddns
+)
+
#################################################
# should we build libsmbclient?
INSTALL_LIBSMBCLIENT=
@@ -4499,6 +4761,7 @@ AC_ARG_WITH(libsmbsharemodes,
LIBSMBSHAREMODES=libsmbsharemodes
fi
INSTALL_LIBSMBSHAREMODES=installlibsmbsharemodes
+ UNINSTALL_LIBSMBSHAREMODES=uninstalllibsmbsharemodes
;;
esac ],
[
@@ -4566,6 +4829,16 @@ if test $space = no; then
fi
fi
+# smbd/statvfs.c assumes that statvfs.f_fsid is an integer.
+# This is not the case on ancient Linux systems.
+
+AC_CACHE_CHECK([that statvfs.f_fsid is an integer],samba_cv_fsid_int, [
+ AC_TRY_COMPILE([#include <sys/statvfs.h>],[struct statvfs buf; buf.f_fsid = 0],
+ samba_cv_fsid_int=yes,samba_cv_fsid_int=no)])
+if test x"$samba_cv_fsid_int" = x"yes"; then
+ AC_DEFINE(HAVE_FSID_INT, 1, [Whether statvfs.f_fsid is an integer])
+fi
+
if test $space = no; then
# DEC Alpha running OSF/1
AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])
@@ -4724,30 +4997,6 @@ if test x"$samba_cv_HAVE_EXPLICIT_LARGEFILE_SUPPORT" = x"yes"; then
fi
AC_MSG_RESULT([$samba_cv_HAVE_EXPLICIT_LARGEFILE_SUPPORT])
-AC_ARG_WITH(spinlocks,
-[ --with-spinlocks Use spin locks instead of fcntl locks (default=no) ])
-if test "x$with_spinlocks" = "xyes"; then
- AC_DEFINE(USE_SPINLOCKS,1,[Whether to use spin locks instead of fcntl locks])
-
- case "$host_cpu" in
- sparc)
- AC_DEFINE(SPARC_SPINLOCKS,1,[Whether to use sparc spinlocks])
- ;;
-
- i386|i486|i586|i686)
- AC_DEFINE(INTEL_SPINLOCKS,1,[Whether to use intel spinlocks])
- ;;
-
- mips)
- AC_DEFINE(MIPS_SPINLOCKS,1,[Whether to use mips spinlocks])
- ;;
-
- powerpc)
- AC_DEFINE(POWERPC_SPINLOCKS,1,[Whether to use powerpc spinlocks])
- ;;
- esac
-fi
-
#################################################
# check for cluster extensions
@@ -4775,28 +5024,34 @@ AC_ARG_WITH(acl-support,
*sysv5*)
AC_MSG_RESULT(Using UnixWare ACLs)
AC_DEFINE(HAVE_UNIXWARE_ACLS,1,[Whether UnixWare ACLs are available])
+ default_static_modules="$default_static_modules vfs_solarisacl"
;;
*solaris*)
AC_MSG_RESULT(Using solaris ACLs)
AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether solaris ACLs are available])
ACL_LIBS="$ACL_LIBS -lsec"
+ default_static_modules="$default_static_modules vfs_solarisacl"
;;
*hpux*)
AC_MSG_RESULT(Using HPUX ACLs)
AC_DEFINE(HAVE_HPUX_ACLS,1,[Whether HPUX ACLs are available])
+ default_static_modules="$default_static_modules vfs_hpuxacl"
;;
*irix*)
AC_MSG_RESULT(Using IRIX ACLs)
AC_DEFINE(HAVE_IRIX_ACLS,1,[Whether IRIX ACLs are available])
+ default_static_modules="$default_static_modules vfs_irixacl"
;;
*aix*)
AC_MSG_RESULT(Using AIX ACLs)
AC_DEFINE(HAVE_AIX_ACLS,1,[Whether AIX ACLs are available])
+ default_static_modules="$default_static_modules vfs_aixacl"
;;
*osf*)
AC_MSG_RESULT(Using Tru64 ACLs)
AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available])
ACL_LIBS="$ACL_LIBS -lpacl"
+ default_static_modules="$default_static_modules vfs_tru64acl"
;;
*freebsd[[5-9]]*)
AC_MSG_RESULT(Using FreeBSD posix ACLs)
@@ -4807,54 +5062,84 @@ AC_ARG_WITH(acl-support,
AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"])
AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"])
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
- acl_LIBS=$LIBS
- LIBS="$LIBS -lacl"
- AC_TRY_LINK([#include <sys/types.h>
-#include <sys/acl.h>],
-[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);],
-samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)
- LIBS=$acl_LIBS])
- if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
- AC_MSG_RESULT(Using posix ACLs)
- AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available])
- AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
+ acl_LIBS=$LIBS
+ LIBS="$LIBS -lacl"
+ AC_TRY_LINK([
+ #include <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ acl_t acl;
+ int entry_id;
+ acl_entry_t *entry_p;
+ return acl_get_entry(acl, entry_id, entry_p);
+ ],
+ [samba_cv_HAVE_POSIX_ACLS=yes],
+ [samba_cv_HAVE_POSIX_ACLS=no])
+ LIBS=$acl_LIBS
+ ])
+ if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
+ AC_MSG_RESULT(Using posix ACLs)
+ AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available])
+ AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
acl_LIBS=$LIBS
LIBS="$LIBS -lacl"
- AC_TRY_LINK([#include <sys/types.h>
-#include <sys/acl.h>],
-[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);],
-samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)
- LIBS=$acl_LIBS])
- if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
- AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
- fi
+ AC_TRY_LINK([
+ #include <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ acl_permset_t permset_d;
+ acl_perm_t perm;
+ return acl_get_perm_np(permset_d, perm);
+ ],
+ [samba_cv_HAVE_ACL_GET_PERM_NP=yes],
+ [samba_cv_HAVE_ACL_GET_PERM_NP=no])
+ LIBS=$acl_LIBS
+ ])
+ if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
+ AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
fi
+ fi
;;
*)
AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"])
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
- acl_LIBS=$LIBS
- LIBS="$LIBS -lacl"
- AC_TRY_LINK([#include <sys/types.h>
-#include <sys/acl.h>],
-[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);],
-samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)
- LIBS=$acl_LIBS])
- if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
- AC_MSG_RESULT(Using posix ACLs)
- AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available])
- AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
+ acl_LIBS=$LIBS
+ LIBS="$LIBS -lacl"
+ AC_TRY_LINK([
+ #include <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ acl_t acl;
+ int entry_id;
+ acl_entry_t *entry_p;
+ return acl_get_entry( acl, entry_id, entry_p);
+ ],
+ [samba_cv_HAVE_POSIX_ACLS=yes],
+ [samba_cv_HAVE_POSIX_ACLS=no])
+ LIBS=$acl_LIBS
+ ])
+ if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
+ AC_MSG_RESULT(Using posix ACLs)
+ AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available])
+ AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
acl_LIBS=$LIBS
LIBS="$LIBS -lacl"
- AC_TRY_LINK([#include <sys/types.h>
-#include <sys/acl.h>],
-[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);],
-samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)
- LIBS=$acl_LIBS])
- if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
- AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
- fi
+ AC_TRY_LINK([
+ #include <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ acl_permset_t permset_d;
+ acl_perm_t perm;
+ return acl_get_perm_np( permset_d, perm);
+ ],
+ [samba_cv_HAVE_ACL_GET_PERM_NP=yes],
+ [samba_cv_HAVE_ACL_GET_PERM_NP=no])
+ LIBS=$acl_LIBS
+ ])
+ if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
+ AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
fi
+ fi
;;
esac
;;
@@ -4867,6 +5152,10 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)
AC_MSG_RESULT(no)
)
+if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
+ default_static_modules="$default_static_modules vfs_posixacl"
+fi
+
#################################################
# check for AIO support
@@ -5296,6 +5585,23 @@ case "$host_os" in
WINBIND_NSS="nsswitch/nss_winbind.$SHLIBEXT"
WINBIND_WINS_NSS="nsswitch/nss_wins.$SHLIBEXT"
;;
+
+ *netbsd*[[3-9]]*)
+ # NetBSD winbind client is implemented as a wrapper
+ # around the Linux version. It needs getpwent_r() to
+ # indicate libc's use of the correct nsdispatch API.
+ #
+ if test x"$ac_cv_func_getpwent_r" = x"yes"; then
+ WINBIND_NSS_EXTRA_OBJS="\
+ nsswitch/winbind_nss_netbsd.o \
+ nsswitch/winbind_nss_linux.o"
+ WINBIND_NSS="nsswitch/nss_winbind.$SHLIBEXT"
+ WINBIND_WINS_NSS="nsswitch/nss_wins.$SHLIBEXT"
+ else
+ HAVE_WINBIND=no
+ winbind_no_reason=", getpwent_r is missing on $host_os so winbind is unsupported"
+ fi
+ ;;
*irix*)
# IRIX has differently named shared libraries
WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o"
@@ -5361,6 +5667,11 @@ fi
# Display test results
+if test x"$HAVE_WINBIND" = x"no"; then
+ WINBIND_NSS=""
+ WINBIND_WINS_NSS=""
+fi
+
if test x"$HAVE_WINBIND" = x"yes"; then
AC_MSG_RESULT(yes)
AC_DEFINE(WITH_WINBIND,1,[Whether to build winbind])
@@ -5370,7 +5681,7 @@ if test x"$HAVE_WINBIND" = x"yes"; then
if test $BLDSHARED = true; then
SHLIB_PROGS="$SHLIB_PROGS $WINBIND_NSS $WINBIND_WINS_NSS"
- if test x"$with_pam" = x"yes"; then
+ if test x"$create_pam_modules" = x"yes"; then
PAM_MODULES="$PAM_MODULES pam_winbind"
INSTALL_PAM_MODULES="installpammodules"
UNINSTALL_PAM_MODULES="uninstallpammodules"
@@ -5403,6 +5714,18 @@ AC_CHECK_MEMBERS([struct secmethod_table.method_attrlist], , ,
AC_CHECK_MEMBERS([struct secmethod_table.method_version], , ,
[#include <usersec.h>])
+AC_CACHE_CHECK([for SO_PEERCRED],samba_cv_HAVE_PEERCRED,[
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+[struct ucred cred;
+ socklen_t cred_len;
+ int ret = getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len);
+],
+samba_cv_HAVE_PEERCRED=yes,samba_cv_HAVE_PEERCRED=no,samba_cv_HAVE_PEERCRED=cross)])
+if test x"$samba_cv_HAVE_PEERCRED" = x"yes"; then
+ AC_DEFINE(HAVE_PEERCRED,1,[Whether we can use SO_PEERCRED to get socket credentials])
+fi
+
#################################################
# Check to see if we should use the included popt
@@ -5427,8 +5750,8 @@ fi
AC_MSG_CHECKING(whether to use included popt)
if test x"$INCLUDED_POPT" = x"yes"; then
AC_MSG_RESULT(yes)
- BUILD_POPT='$(POPT_OBJS)'
- POPTLIBS='$(POPT_OBJS)'
+ BUILD_POPT='$(POPT_OBJ)'
+ POPTLIBS='$(POPT_OBJ)'
FLAGS1="-I\$(srcdir)/popt"
else
AC_MSG_RESULT(no)
@@ -5523,9 +5846,13 @@ dnl Always built these modules static
MODULE_rpc_spoolss=STATIC
MODULE_rpc_srv=STATIC
MODULE_idmap_tdb=STATIC
+MODULE_idmap_passdb=STATIC
+MODULE_idmap_nss=STATIC
+
+MODULE_nss_info_template=STATIC
AC_ARG_WITH(static-modules,
-[ --with-static-modules=MODULES Comma-seperated list of names of modules to statically link in],
+[ --with-static-modules=MODULES Comma-separated list of names of modules to statically link in],
[ if test $withval; then
for i in `echo $withval | sed -e 's/,/ /g'`
do
@@ -5534,7 +5861,7 @@ AC_ARG_WITH(static-modules,
fi ])
AC_ARG_WITH(shared-modules,
-[ --with-shared-modules=MODULES Comma-seperated list of names of modules to build shared],
+[ --with-shared-modules=MODULES Comma-separated list of names of modules to build shared],
[ if test $withval; then
for i in `echo $withval | sed -e 's/,/ /g'`
do
@@ -5550,25 +5877,30 @@ SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o)
SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC)
-SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_reg.$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_wkssvc, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC)
SMB_MODULE(rpc_svcctl, \$(RPC_SVCCTL_OBJ), "bin/librpc_svcctl.$SHLIBEXT", RPC)
SMB_MODULE(rpc_ntsvcs, \$(RPC_NTSVCS_OBJ), "bin/librpc_ntsvcs.$SHLIBEXT", RPC)
SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC)
SMB_MODULE(rpc_netdfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
-SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_svc.$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)
-SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP)
-SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/tdb.$SHLIBEXT", IDMAP)
-SMB_MODULE(idmap_rid, sam/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
-SMB_MODULE(idmap_ad, sam/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP)
-SMB_SUBSYSTEM(IDMAP,sam/idmap.o)
+SMB_MODULE(idmap_ldap, nsswitch/idmap_ldap.o, "bin/ldap.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_tdb, nsswitch/idmap_tdb.o, "bin/tdb.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_passdb, nsswitch/idmap_passdb.o, "bin/passdb.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_nss, nsswitch/idmap_nss.o, "bin/nss.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_rid, nsswitch/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_ad, nsswitch/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP)
+SMB_SUBSYSTEM(IDMAP, nsswitch/idmap.o)
+
+SMB_MODULE(nss_info_template, nsswitch/nss_info_template.o, "bin/template.$SHLIBEXT", NSS_INFO)
+SMB_SUBSYSTEM(NSS_INFO, nsswitch/nss_info.o)
SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET)
SMB_MODULE(charset_CP850, modules/CP850.o, "bin/CP850.$SHLIBEXT", CHARSET)
@@ -5585,6 +5917,7 @@ SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH)
SMB_MODULE(auth_script, \$(AUTH_SCRIPT_OBJ), "bin/script.$SHLIBEXT", AUTH)
SMB_SUBSYSTEM(AUTH,auth/auth.o)
+SMB_MODULE(vfs_default, \$(VFS_DEFAULT_OBJ), "bin/default.$SHLIBEXT", VFS)
SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS)
SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS)
SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS)
@@ -5597,7 +5930,19 @@ 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_posixacl, \$(VFS_POSIXACL_OBJ), "bin/posixacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_aixacl, \$(VFS_AIXACL_OBJ), "bin/aixacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_aixacl2, \$(VFS_AIXACL2_OBJ), "bin/aixacl2.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_solarisacl, \$(VFS_SOLARISACL_OBJ), "bin/solarisacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_irixacl, \$(VFS_IRIXACL_OBJ), "bin/irixacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_hpuxacl, \$(VFS_HPUXACL_OBJ), "bin/hpuxacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_tru64acl, \$(VFS_TRU64ACL_OBJ), "bin/tru64acl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_gpfs, \$(VFS_GPFS_OBJ), "bin/gpfs.$SHLIBEXT", VFS)
+
SMB_SUBSYSTEM(VFS,smbd/vfs.o)
AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
@@ -5610,15 +5955,110 @@ if test "${ac_cv_prog_CC}" = "insure"; then
fi
#################################################
+# If run from the build farm, enable NASTY hacks
+#################################################
+AC_MSG_CHECKING(whether to enable build farm hacks)
+if test x"$RUN_FROM_BUILD_FARM" = x"yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(ENABLE_BUILD_FARM_HACKS, 1, [Defined if running in the build farm])
+else
+ AC_MSG_RESULT(no)
+fi
+
+#################################################
+# check for bad librt/libpthread interactions
+
+if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes" -o \
+ x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes" -o \
+ x"$samba_cv_HAVE_AIO64" = x"yes" -o \
+ x"$samba_cv_HAVE_AIO" = x"yes" ; then
+
+SMB_IF_RTSIGNAL_BUG(
+ [
+ # Have RT_SIGNAL bug, need to check whether the problem will
+ # affect anything we have configured.
+
+ rt_do_error=no
+ if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_LINUX" = x"yes"; then
+ if test x"$rt_signal_lease_ok" = x"no" ; then
+ rt_do_error=yes
+ fi
+ fi
+
+ if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then
+ if test x"$rt_signal_notify_ok" = x"no" ; then
+ rt_do_error=yes
+ fi
+ fi
+
+ if test x"$samba_cv_HAVE_AIO64" = x"yes" -o \
+ x"$samba_cv_HAVE_AIO" = x"yes" ; then
+ if test x"$rt_signal_aio_ok" = x"no" ; then
+ rt_do_error=yes
+ fi
+ fi
+
+ if test x"$rt_do_error" = x"yes" ; then
+ SMB_IS_LIBPTHREAD_LINKED(
+ [
+ cat<<MSG
+
+*** On this platforms, linking Samba against pthreads causes problems
+*** with the oplock and change notification mechanisms. You may be
+*** using pthreads as a side-effect of using the --with-aio-support
+*** or --with-profiling-data options. Please remove these and try again.
+
+MSG
+ ],
+ [
+ cat<<MSG
+
+*** On this platform, the oplock and change notification mechanisms do not
+*** appear to work. Please report this problem to samba-technical@samba.org
+*** and attach the config.log file from this directory.
+
+MSG
+ ])
+ AC_MSG_ERROR(unable to use realtime signals on this platform)
+ fi
+ ],
+ [
+ # no RT_SIGNAL bug, we are golden
+ SMB_IS_LIBPTHREAD_LINKED(
+ [
+ AC_MSG_WARN(using libpthreads - this may degrade performance)
+ ])
+
+ ],
+ [
+ # cross compiling, I hope you know what you are doing
+ true
+ ])
+
+fi
+
+dnl Remove -L/usr/lib/? from LDFLAGS and LIBS
+LIB_REMOVE_USR_LIB(LDFLAGS)
+LIB_REMOVE_USR_LIB(LIBS)
+LIB_REMOVE_USR_LIB(KRB5_LIBS)
+
+dnl Remove -I/usr/include/? from CFLAGS and CPPFLAGS
+CFLAGS_REMOVE_USR_INCLUDE(CFLAGS)
+CFLAGS_REMOVE_USR_INCLUDE(CPPFLAGS)
+
+#################################################
# Display summary of libraries detected
AC_MSG_RESULT([Using libraries:])
AC_MSG_RESULT([ LIBS = $LIBS])
if test x"$with_ads_support" != x"no"; then
- AC_MSG_RESULT([ KRB5_LIBS = $KRB5_LIBS])
+ AC_MSG_RESULT([ KRB5_LIBS = $KRB5_LIBS])
fi
if test x"$with_ldap_support" != x"no"; then
- AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS])
+ AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS])
+fi
+if test x"$with_dnsupdate_support" != x"no"; then
+ AC_MSG_RESULT([ UUID_LIBS = $UUID_LIBS])
fi
AC_MSG_RESULT([ AUTH_LIBS = $AUTH_LIBS])
@@ -5639,14 +6079,6 @@ AC_SUBST(builddir)
SMBD_LIBS="$samba_fam_libs $samba_dmapi_libs"
AC_SUBST(SMBD_LIBS)
-dnl Remove -L/usr/lib/? from LDFLAGS and LIBS
-LIB_REMOVE_USR_LIB(LDFLAGS)
-LIB_REMOVE_USR_LIB(LIBS)
-
-dnl Remove -I/usr/include/? from CFLAGS and CPPFLAGS
-CFLAGS_REMOVE_USR_INCLUDE(CFLAGS)
-CFLAGS_REMOVE_USR_INCLUDE(CPPFLAGS)
-
AC_OUTPUT(include/stamp-h Makefile script/findsmb smbadduser script/gen-8bit-gap.sh script/installbin.sh script/uninstallbin.sh)
#################################################
diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c
index 902068204ac..54cffd15882 100644
--- a/source/groupdb/mapping.c
+++ b/source/groupdb/mapping.c
@@ -22,121 +22,12 @@
*/
#include "includes.h"
-
-static TDB_CONTEXT *tdb; /* used for driver files */
-
-#define DATABASE_VERSION_V1 1 /* native byte format. */
-#define DATABASE_VERSION_V2 2 /* le format. */
-
-#define GROUP_PREFIX "UNIXGROUP/"
-
-/* Alias memberships are stored reverse, as memberships. The performance
- * critical operation is to determine the aliases a SID is member of, not
- * listing alias members. So we store a list of alias SIDs a SID is member of
- * hanging of the member as key.
- */
-#define MEMBEROF_PREFIX "MEMBEROF/"
-
-
-static BOOL enum_group_mapping(const DOM_SID *sid, enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
- size_t *p_num_entries, BOOL unix_only);
-static BOOL group_map_remove(const DOM_SID *sid);
-
-/****************************************************************************
- Open the group mapping tdb.
-****************************************************************************/
-
-static BOOL init_group_mapping(void)
-{
- const char *vstring = "INFO/version";
- int32 vers_id;
- GROUP_MAP *map_table = NULL;
- size_t num_entries = 0;
-
- if (tdb)
- return True;
-
- tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
- if (!tdb) {
- DEBUG(0,("Failed to open group mapping database\n"));
- return False;
- }
-
- /* handle a Samba upgrade */
- tdb_lock_bystring(tdb, vstring);
-
- /* Cope with byte-reversed older versions of the db. */
- vers_id = tdb_fetch_int32(tdb, vstring);
- if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
- /* Written on a bigendian machine with old fetch_int code. Save as le. */
- tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
- vers_id = DATABASE_VERSION_V2;
- }
-
- /* if its an unknown version we remove everthing in the db */
-
- if (vers_id != DATABASE_VERSION_V2) {
- tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
- tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
- }
-
- tdb_unlock_bystring(tdb, vstring);
-
- /* cleanup any map entries with a gid == -1 */
-
- if ( enum_group_mapping( NULL, SID_NAME_UNKNOWN, &map_table, &num_entries, False ) ) {
- int i;
-
- for ( i=0; i<num_entries; i++ ) {
- if ( map_table[i].gid == -1 ) {
- group_map_remove( &map_table[i].sid );
- }
- }
-
- SAFE_FREE( map_table );
- }
-
-
- return True;
-}
-
-/****************************************************************************
-****************************************************************************/
-static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
-{
- TDB_DATA kbuf, dbuf;
- pstring key, buf;
- fstring string_sid="";
- int len;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- sid_to_string(string_sid, &map->sid);
-
- len = tdb_pack(buf, sizeof(buf), "ddff",
- map->gid, map->sid_name_use, map->nt_name, map->comment);
-
- if (len > sizeof(buf))
- return False;
-
- slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
-
- kbuf.dsize = strlen(key)+1;
- kbuf.dptr = key;
- dbuf.dsize = len;
- dbuf.dptr = buf;
- if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
-
- return True;
-}
+#include "groupdb/mapping.h"
/****************************************************************************
initialise first time the mapping list
****************************************************************************/
-NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
+NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum lsa_SidType sid_name_use, const char *nt_name, const char *comment)
{
GROUP_MAP map;
@@ -216,327 +107,11 @@ NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
return status;
}
-/****************************************************************************
- Return the sid and the type of the unix group.
-****************************************************************************/
-
-static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
-{
- TDB_DATA kbuf, dbuf;
- pstring key;
- fstring string_sid;
- int ret = 0;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- /* the key is the SID, retrieving is direct */
-
- sid_to_string(string_sid, &sid);
- slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
-
- kbuf.dptr = key;
- kbuf.dsize = strlen(key)+1;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- return False;
-
- ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
- &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
-
- SAFE_FREE(dbuf.dptr);
-
- if ( ret == -1 ) {
- DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
- return False;
- }
-
- sid_copy(&map->sid, &sid);
-
- return True;
-}
-
-/****************************************************************************
- Return the sid and the type of the unix group.
-****************************************************************************/
-
-static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
-{
- TDB_DATA kbuf, dbuf, newkey;
- fstring string_sid;
- int ret;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- /* we need to enumerate the TDB to find the GID */
-
- for (kbuf = tdb_firstkey(tdb);
- kbuf.dptr;
- newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
-
- if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- continue;
-
- fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
-
- string_to_sid(&map->sid, string_sid);
-
- ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
- &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
-
- SAFE_FREE(dbuf.dptr);
-
- if ( ret == -1 ) {
- DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n"));
- return False;
- }
-
- if (gid==map->gid) {
- SAFE_FREE(kbuf.dptr);
- return True;
- }
- }
-
- return False;
-}
-
-/****************************************************************************
- Return the sid and the type of the unix group.
-****************************************************************************/
-
-static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
-{
- TDB_DATA kbuf, dbuf, newkey;
- fstring string_sid;
- int ret;
-
- if(!init_group_mapping()) {
- DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping\n"));
- return(False);
- }
-
- /* we need to enumerate the TDB to find the name */
- for (kbuf = tdb_firstkey(tdb);
- kbuf.dptr;
- newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
- if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- continue;
- fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
- string_to_sid(&map->sid, string_sid);
-
- ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
- &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
- SAFE_FREE(dbuf.dptr);
-
- if ( ret == -1 ) {
- DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n"));
- return False;
- }
-
- if ( strequal(name, map->nt_name) ) {
- SAFE_FREE(kbuf.dptr);
- return True;
- }
- }
-
- return False;
-}
-
-/****************************************************************************
- Remove a group mapping entry.
-****************************************************************************/
-
-static BOOL group_map_remove(const DOM_SID *sid)
-{
- TDB_DATA kbuf, dbuf;
- pstring key;
- fstring string_sid;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- /* the key is the SID, retrieving is direct */
-
- sid_to_string(string_sid, sid);
- slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
-
- kbuf.dptr = key;
- kbuf.dsize = strlen(key)+1;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- return False;
-
- SAFE_FREE(dbuf.dptr);
-
- if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
- return False;
-
- return True;
-}
-
-/****************************************************************************
- Enumerate the group mapping.
-****************************************************************************/
-
-static BOOL enum_group_mapping(const DOM_SID *domsid, enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
- size_t *p_num_entries, BOOL unix_only)
-{
- TDB_DATA kbuf, dbuf, newkey;
- fstring string_sid;
- GROUP_MAP map;
- GROUP_MAP *mapt;
- int ret;
- size_t entries=0;
- DOM_SID grpsid;
- uint32 rid;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- *p_num_entries=0;
- *pp_rmap=NULL;
-
- for (kbuf = tdb_firstkey(tdb);
- kbuf.dptr;
- newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
-
- if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
- continue;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- continue;
-
- fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
-
- ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
- &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
-
- SAFE_FREE(dbuf.dptr);
-
- if ( ret == -1 ) {
- DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
- continue;
- }
-
- /* list only the type or everything if UNKNOWN */
- if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) {
- DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
- continue;
- }
-
- if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
- DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
- continue;
- }
-
- string_to_sid(&grpsid, string_sid);
- sid_copy( &map.sid, &grpsid );
-
- sid_split_rid( &grpsid, &rid );
-
- /* Only check the domain if we were given one */
-
- if ( domsid && !sid_equal( domsid, &grpsid ) ) {
- DEBUG(11,("enum_group_mapping: group %s is not in domain %s\n",
- string_sid, sid_string_static(domsid)));
- continue;
- }
-
- DEBUG(11,("enum_group_mapping: returning group %s of "
- "type %s\n", map.nt_name,
- sid_type_lookup(map.sid_name_use)));
-
- (*pp_rmap) = SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
- if (!(*pp_rmap)) {
- DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
- return False;
- }
-
- mapt = (*pp_rmap);
-
- mapt[entries].gid = map.gid;
- sid_copy( &mapt[entries].sid, &map.sid);
- mapt[entries].sid_name_use = map.sid_name_use;
- fstrcpy(mapt[entries].nt_name, map.nt_name);
- fstrcpy(mapt[entries].comment, map.comment);
-
- entries++;
-
- }
-
- *p_num_entries=entries;
-
- return True;
-}
-
-/* This operation happens on session setup, so it should better be fast. We
- * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
-
-static NTSTATUS one_alias_membership(const DOM_SID *member,
- DOM_SID **sids, size_t *num)
-{
- fstring key, string_sid;
- TDB_DATA kbuf, dbuf;
- const char *p;
-
- if (!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- sid_to_string(string_sid, member);
- slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
-
- kbuf.dsize = strlen(key)+1;
- kbuf.dptr = key;
-
- dbuf = tdb_fetch(tdb, kbuf);
-
- if (dbuf.dptr == NULL) {
- return NT_STATUS_OK;
- }
-
- p = dbuf.dptr;
-
- while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
-
- DOM_SID alias;
-
- if (!string_to_sid(&alias, string_sid))
- continue;
-
- add_sid_to_array_unique(NULL, &alias, sids, num);
-
- if (sids == NULL)
- return NT_STATUS_NO_MEMORY;
- }
-
- SAFE_FREE(dbuf.dptr);
- return NT_STATUS_OK;
-}
static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members,
DOM_SID **sids, size_t *num)
@@ -554,235 +129,13 @@ static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members,
return NT_STATUS_OK;
}
-static BOOL is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
-{
- DOM_SID *sids;
- size_t i, num;
-
- /* This feels the wrong way round, but the on-disk data structure
- * dictates it this way. */
- if (!NT_STATUS_IS_OK(alias_memberships(member, 1, &sids, &num)))
- return False;
-
- for (i=0; i<num; i++) {
- if (sid_compare(alias, &sids[i]) == 0) {
- SAFE_FREE(sids);
- return True;
- }
- }
- SAFE_FREE(sids);
- return False;
-}
-
-static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
-{
- GROUP_MAP map;
- TDB_DATA kbuf, dbuf;
- pstring key;
- fstring string_sid;
- char *new_memberstring;
- int result;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!get_group_map_from_sid(*alias, &map))
- return NT_STATUS_NO_SUCH_ALIAS;
-
- if ( (map.sid_name_use != SID_NAME_ALIAS) &&
- (map.sid_name_use != SID_NAME_WKN_GRP) )
- return NT_STATUS_NO_SUCH_ALIAS;
-
- if (is_aliasmem(alias, member))
- return NT_STATUS_MEMBER_IN_ALIAS;
-
- sid_to_string(string_sid, member);
- slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
-
- kbuf.dsize = strlen(key)+1;
- kbuf.dptr = key;
-
- dbuf = tdb_fetch(tdb, kbuf);
-
- sid_to_string(string_sid, alias);
-
- if (dbuf.dptr != NULL) {
- asprintf(&new_memberstring, "%s %s", (char *)(dbuf.dptr),
- string_sid);
- } else {
- new_memberstring = SMB_STRDUP(string_sid);
- }
-
- if (new_memberstring == NULL)
- return NT_STATUS_NO_MEMORY;
-
- SAFE_FREE(dbuf.dptr);
- dbuf.dsize = strlen(new_memberstring)+1;
- dbuf.dptr = new_memberstring;
-
- result = tdb_store(tdb, kbuf, dbuf, 0);
-
- SAFE_FREE(new_memberstring);
-
- return (result == 0 ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
-}
-
struct aliasmem_closure {
const DOM_SID *alias;
DOM_SID **sids;
size_t *num;
};
-static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data,
- void *state)
-{
- struct aliasmem_closure *closure = (struct aliasmem_closure *)state;
- const char *p;
- fstring alias_string;
-
- if (strncmp(key.dptr, MEMBEROF_PREFIX,
- strlen(MEMBEROF_PREFIX)) != 0)
- return 0;
-
- p = data.dptr;
-
- while (next_token(&p, alias_string, " ", sizeof(alias_string))) {
-
- DOM_SID alias, member;
- const char *member_string;
-
-
- if (!string_to_sid(&alias, alias_string))
- continue;
-
- if (sid_compare(closure->alias, &alias) != 0)
- continue;
-
- /* Ok, we found the alias we're looking for in the membership
- * list currently scanned. The key represents the alias
- * member. Add that. */
-
- member_string = strchr(key.dptr, '/');
-
- /* Above we tested for MEMBEROF_PREFIX which includes the
- * slash. */
-
- SMB_ASSERT(member_string != NULL);
- member_string += 1;
-
- if (!string_to_sid(&member, member_string))
- continue;
-
- add_sid_to_array(NULL, &member, closure->sids, closure->num);
- }
-
- return 0;
-}
-
-static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
-{
- GROUP_MAP map;
- struct aliasmem_closure closure;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!get_group_map_from_sid(*alias, &map))
- return NT_STATUS_NO_SUCH_ALIAS;
-
- if ( (map.sid_name_use != SID_NAME_ALIAS) &&
- (map.sid_name_use != SID_NAME_WKN_GRP) )
- return NT_STATUS_NO_SUCH_ALIAS;
-
- *sids = NULL;
- *num = 0;
-
- closure.alias = alias;
- closure.sids = sids;
- closure.num = num;
-
- tdb_traverse(tdb, collect_aliasmem, &closure);
- return NT_STATUS_OK;
-}
-
-static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
-{
- NTSTATUS result;
- DOM_SID *sids;
- size_t i, num;
- BOOL found = False;
- char *member_string;
- TDB_DATA kbuf, dbuf;
- pstring key;
- fstring sid_string;
-
- result = alias_memberships(member, 1, &sids, &num);
-
- if (!NT_STATUS_IS_OK(result))
- return result;
-
- for (i=0; i<num; i++) {
- if (sid_compare(&sids[i], alias) == 0) {
- found = True;
- break;
- }
- }
- if (!found) {
- SAFE_FREE(sids);
- return NT_STATUS_MEMBER_NOT_IN_ALIAS;
- }
-
- if (i < num)
- sids[i] = sids[num-1];
-
- num -= 1;
-
- sid_to_string(sid_string, member);
- slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, sid_string);
-
- kbuf.dsize = strlen(key)+1;
- kbuf.dptr = key;
-
- if (num == 0)
- return tdb_delete(tdb, kbuf) == 0 ?
- NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
-
- member_string = SMB_STRDUP("");
-
- if (member_string == NULL) {
- SAFE_FREE(sids);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<num; i++) {
- char *s = member_string;
-
- sid_to_string(sid_string, &sids[i]);
- asprintf(&member_string, "%s %s", s, sid_string);
-
- SAFE_FREE(s);
- if (member_string == NULL) {
- SAFE_FREE(sids);
- return NT_STATUS_NO_MEMORY;
- }
- }
-
- dbuf.dsize = strlen(member_string)+1;
- dbuf.dptr = member_string;
-
- result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ?
- NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
-
- SAFE_FREE(sids);
- SAFE_FREE(member_string);
-
- return result;
-}
/*
*
@@ -1055,7 +408,7 @@ NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
}
NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
- const DOM_SID *sid, enum SID_NAME_USE sid_name_use,
+ const DOM_SID *sid, enum lsa_SidType sid_name_use,
GROUP_MAP **pp_rmap, size_t *p_num_entries,
BOOL unix_only)
{
@@ -1083,7 +436,7 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
const char *name, uint32 *rid)
{
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
uint32 new_rid;
gid_t gid;
BOOL exists;
@@ -1238,7 +591,7 @@ NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
*p_num_alias_rids += 1;
}
- SAFE_FREE(alias_sids);
+ TALLOC_FREE(alias_sids);
return NT_STATUS_OK;
}
@@ -1284,7 +637,7 @@ NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
}
NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
- enum SID_NAME_USE sid_name_use,
+ enum lsa_SidType sid_name_use,
GROUP_MAP **rmap, size_t *num_entries,
BOOL unix_only)
{
@@ -1332,7 +685,7 @@ BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
NTSTATUS pdb_create_builtin_alias(uint32 rid)
{
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
gid_t gid;
GROUP_MAP map;
TALLOC_CTX *mem_ctx;
diff --git a/source/groupdb/mapping.h b/source/groupdb/mapping.h
new file mode 100644
index 00000000000..9daaa7fdd78
--- /dev/null
+++ b/source/groupdb/mapping.h
@@ -0,0 +1,26 @@
+#define DATABASE_VERSION_V1 1 /* native byte format. */
+#define DATABASE_VERSION_V2 2 /* le format. */
+
+#define GROUP_PREFIX "UNIXGROUP/"
+
+/* Alias memberships are stored reverse, as memberships. The performance
+ * critical operation is to determine the aliases a SID is member of, not
+ * listing alias members. So we store a list of alias SIDs a SID is member of
+ * hanging of the member as key.
+ */
+#define MEMBEROF_PREFIX "MEMBEROF/"
+
+/* internal prototypes */
+BOOL enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, GROUP_MAP **pp_rmap,
+ size_t *p_num_entries, BOOL unix_only);
+BOOL group_map_remove(const DOM_SID *sid);
+BOOL init_group_mapping(void);
+NTSTATUS one_alias_membership(const DOM_SID *member,
+ DOM_SID **sids, size_t *num);
+BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map);
+BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map);
+BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map);
+BOOL add_mapping_entry(GROUP_MAP *map, int flag);
+NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member);
+NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member);
+NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num);
diff --git a/source/groupdb/mapping_tdb.c b/source/groupdb/mapping_tdb.c
new file mode 100644
index 00000000000..cff557ff133
--- /dev/null
+++ b/source/groupdb/mapping_tdb.c
@@ -0,0 +1,690 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-2006,
+ * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Volker Lendecke 2006.
+ * Copyright (C) Gerald Carter 2006.
+ *
+ * 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 "groupdb/mapping.h"
+
+static TDB_CONTEXT *tdb; /* used for driver files */
+
+/****************************************************************************
+ Open the group mapping tdb.
+****************************************************************************/
+ BOOL init_group_mapping(void)
+{
+ const char *vstring = "INFO/version";
+ int32 vers_id;
+ GROUP_MAP *map_table = NULL;
+ size_t num_entries = 0;
+
+ if (tdb)
+ return True;
+
+ tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ if (!tdb) {
+ DEBUG(0,("Failed to open group mapping database\n"));
+ return False;
+ }
+
+ /* handle a Samba upgrade */
+ tdb_lock_bystring(tdb, vstring);
+
+ /* Cope with byte-reversed older versions of the db. */
+ vers_id = tdb_fetch_int32(tdb, vstring);
+ if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
+ /* Written on a bigendian machine with old fetch_int code. Save as le. */
+ tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
+ vers_id = DATABASE_VERSION_V2;
+ }
+
+ /* if its an unknown version we remove everthing in the db */
+
+ if (vers_id != DATABASE_VERSION_V2) {
+ tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
+ tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
+ }
+
+ tdb_unlock_bystring(tdb, vstring);
+
+ /* cleanup any map entries with a gid == -1 */
+
+ if ( enum_group_mapping( NULL, SID_NAME_UNKNOWN, &map_table, &num_entries, False ) ) {
+ int i;
+
+ for ( i=0; i<num_entries; i++ ) {
+ if ( map_table[i].gid == -1 ) {
+ group_map_remove( &map_table[i].sid );
+ }
+ }
+
+ SAFE_FREE( map_table );
+ }
+
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+ BOOL add_mapping_entry(GROUP_MAP *map, int flag)
+{
+ TDB_DATA kbuf, dbuf;
+ pstring key, buf;
+ fstring string_sid="";
+ int len;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ sid_to_string(string_sid, &map->sid);
+
+ len = tdb_pack(buf, sizeof(buf), "ddff",
+ map->gid, map->sid_name_use, map->nt_name, map->comment);
+
+ if (len > sizeof(buf))
+ return False;
+
+ slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
+
+ kbuf.dsize = strlen(key)+1;
+ kbuf.dptr = key;
+ dbuf.dsize = len;
+ dbuf.dptr = buf;
+ if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
+
+ return True;
+}
+
+
+/****************************************************************************
+ Return the sid and the type of the unix group.
+****************************************************************************/
+
+ BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
+{
+ TDB_DATA kbuf, dbuf;
+ pstring key;
+ fstring string_sid;
+ int ret = 0;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ /* the key is the SID, retrieving is direct */
+
+ sid_to_string(string_sid, &sid);
+ slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
+
+ kbuf.dptr = key;
+ kbuf.dsize = strlen(key)+1;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ return False;
+
+ ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
+ &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
+
+ SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
+ return False;
+ }
+
+ sid_copy(&map->sid, &sid);
+
+ return True;
+}
+
+/****************************************************************************
+ Return the sid and the type of the unix group.
+****************************************************************************/
+
+ BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
+{
+ TDB_DATA kbuf, dbuf, newkey;
+ fstring string_sid;
+ int ret;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ /* we need to enumerate the TDB to find the GID */
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
+
+ if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ continue;
+
+ fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
+
+ string_to_sid(&map->sid, string_sid);
+
+ ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
+ &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
+
+ SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n"));
+ return False;
+ }
+
+ if (gid==map->gid) {
+ SAFE_FREE(kbuf.dptr);
+ return True;
+ }
+ }
+
+ return False;
+}
+
+/****************************************************************************
+ Return the sid and the type of the unix group.
+****************************************************************************/
+
+ BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
+{
+ TDB_DATA kbuf, dbuf, newkey;
+ fstring string_sid;
+ int ret;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ /* we need to enumerate the TDB to find the name */
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
+
+ if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ continue;
+
+ fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
+
+ string_to_sid(&map->sid, string_sid);
+
+ ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
+ &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
+
+ SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n"));
+ return False;
+ }
+
+ if ( strequal(name, map->nt_name) ) {
+ SAFE_FREE(kbuf.dptr);
+ return True;
+ }
+ }
+
+ return False;
+}
+
+/****************************************************************************
+ Remove a group mapping entry.
+****************************************************************************/
+
+BOOL group_map_remove(const DOM_SID *sid)
+{
+ TDB_DATA kbuf, dbuf;
+ pstring key;
+ fstring string_sid;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ /* the key is the SID, retrieving is direct */
+
+ sid_to_string(string_sid, sid);
+ slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
+
+ kbuf.dptr = key;
+ kbuf.dsize = strlen(key)+1;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ return False;
+
+ SAFE_FREE(dbuf.dptr);
+
+ if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
+ return False;
+
+ return True;
+}
+
+/****************************************************************************
+ Enumerate the group mapping.
+****************************************************************************/
+
+BOOL enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, GROUP_MAP **pp_rmap,
+ size_t *p_num_entries, BOOL unix_only)
+{
+ TDB_DATA kbuf, dbuf, newkey;
+ fstring string_sid;
+ GROUP_MAP map;
+ GROUP_MAP *mapt;
+ int ret;
+ size_t entries=0;
+ DOM_SID grpsid;
+ uint32 rid;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return(False);
+ }
+
+ *p_num_entries=0;
+ *pp_rmap=NULL;
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
+
+ if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
+ continue;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ continue;
+
+ fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
+
+ ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
+ &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
+
+ SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
+ continue;
+ }
+
+ /* list only the type or everything if UNKNOWN */
+ if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) {
+ DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
+ continue;
+ }
+
+ if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
+ DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
+ continue;
+ }
+
+ string_to_sid(&grpsid, string_sid);
+ sid_copy( &map.sid, &grpsid );
+
+ sid_split_rid( &grpsid, &rid );
+
+ /* Only check the domain if we were given one */
+
+ if ( domsid && !sid_equal( domsid, &grpsid ) ) {
+ DEBUG(11,("enum_group_mapping: group %s is not in domain %s\n",
+ string_sid, sid_string_static(domsid)));
+ continue;
+ }
+
+ DEBUG(11,("enum_group_mapping: returning group %s of "
+ "type %s\n", map.nt_name,
+ sid_type_lookup(map.sid_name_use)));
+
+ (*pp_rmap) = SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
+ if (!(*pp_rmap)) {
+ DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
+ return False;
+ }
+
+ mapt = (*pp_rmap);
+
+ mapt[entries].gid = map.gid;
+ sid_copy( &mapt[entries].sid, &map.sid);
+ mapt[entries].sid_name_use = map.sid_name_use;
+ fstrcpy(mapt[entries].nt_name, map.nt_name);
+ fstrcpy(mapt[entries].comment, map.comment);
+
+ entries++;
+
+ }
+
+ *p_num_entries=entries;
+
+ return True;
+}
+
+/* This operation happens on session setup, so it should better be fast. We
+ * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
+
+ NTSTATUS one_alias_membership(const DOM_SID *member,
+ DOM_SID **sids, size_t *num)
+{
+ fstring key, string_sid;
+ TDB_DATA kbuf, dbuf;
+ const char *p;
+
+ if (!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ sid_to_string(string_sid, member);
+ slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
+
+ kbuf.dsize = strlen(key)+1;
+ kbuf.dptr = key;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+
+ if (dbuf.dptr == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ p = dbuf.dptr;
+
+ while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
+
+ DOM_SID alias;
+
+ if (!string_to_sid(&alias, string_sid))
+ continue;
+
+ if (!add_sid_to_array_unique(NULL, &alias, sids, num)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ SAFE_FREE(dbuf.dptr);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members,
+ DOM_SID **sids, size_t *num)
+{
+ size_t i;
+
+ *num = 0;
+ *sids = NULL;
+
+ for (i=0; i<num_members; i++) {
+ NTSTATUS status = one_alias_membership(&members[i], sids, num);
+ if (!NT_STATUS_IS_OK(status))
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
+static BOOL is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+{
+ DOM_SID *sids;
+ size_t i, num;
+
+ /* This feels the wrong way round, but the on-disk data structure
+ * dictates it this way. */
+ if (!NT_STATUS_IS_OK(alias_memberships(member, 1, &sids, &num)))
+ return False;
+
+ for (i=0; i<num; i++) {
+ if (sid_compare(alias, &sids[i]) == 0) {
+ SAFE_FREE(sids);
+ return True;
+ }
+ }
+ SAFE_FREE(sids);
+ return False;
+}
+
+
+ NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+{
+ GROUP_MAP map;
+ TDB_DATA kbuf, dbuf;
+ pstring key;
+ fstring string_sid;
+ char *new_memberstring;
+ int result;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!get_group_map_from_sid(*alias, &map))
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ if ( (map.sid_name_use != SID_NAME_ALIAS) &&
+ (map.sid_name_use != SID_NAME_WKN_GRP) )
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ if (is_aliasmem(alias, member))
+ return NT_STATUS_MEMBER_IN_ALIAS;
+
+ sid_to_string(string_sid, member);
+ slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
+
+ kbuf.dsize = strlen(key)+1;
+ kbuf.dptr = key;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+
+ sid_to_string(string_sid, alias);
+
+ if (dbuf.dptr != NULL) {
+ asprintf(&new_memberstring, "%s %s", (char *)(dbuf.dptr),
+ string_sid);
+ } else {
+ new_memberstring = SMB_STRDUP(string_sid);
+ }
+
+ if (new_memberstring == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ SAFE_FREE(dbuf.dptr);
+ dbuf.dsize = strlen(new_memberstring)+1;
+ dbuf.dptr = new_memberstring;
+
+ result = tdb_store(tdb, kbuf, dbuf, 0);
+
+ SAFE_FREE(new_memberstring);
+
+ return (result == 0 ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
+}
+
+struct aliasmem_closure {
+ const DOM_SID *alias;
+ DOM_SID **sids;
+ size_t *num;
+};
+
+static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data,
+ void *state)
+{
+ struct aliasmem_closure *closure = (struct aliasmem_closure *)state;
+ const char *p;
+ fstring alias_string;
+
+ if (strncmp(key.dptr, MEMBEROF_PREFIX,
+ strlen(MEMBEROF_PREFIX)) != 0)
+ return 0;
+
+ p = data.dptr;
+
+ while (next_token(&p, alias_string, " ", sizeof(alias_string))) {
+
+ DOM_SID alias, member;
+ const char *member_string;
+
+
+ if (!string_to_sid(&alias, alias_string))
+ continue;
+
+ if (sid_compare(closure->alias, &alias) != 0)
+ continue;
+
+ /* Ok, we found the alias we're looking for in the membership
+ * list currently scanned. The key represents the alias
+ * member. Add that. */
+
+ member_string = strchr(key.dptr, '/');
+
+ /* Above we tested for MEMBEROF_PREFIX which includes the
+ * slash. */
+
+ SMB_ASSERT(member_string != NULL);
+ member_string += 1;
+
+ if (!string_to_sid(&member, member_string))
+ continue;
+
+ if (!add_sid_to_array(NULL, &member, closure->sids, closure->num)) {
+ /* talloc fail. */
+ break;
+ }
+ }
+
+ return 0;
+}
+
+ NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
+{
+ GROUP_MAP map;
+ struct aliasmem_closure closure;
+
+ if(!init_group_mapping()) {
+ DEBUG(0,("failed to initialize group mapping\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!get_group_map_from_sid(*alias, &map))
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ if ( (map.sid_name_use != SID_NAME_ALIAS) &&
+ (map.sid_name_use != SID_NAME_WKN_GRP) )
+ return NT_STATUS_NO_SUCH_ALIAS;
+
+ *sids = NULL;
+ *num = 0;
+
+ closure.alias = alias;
+ closure.sids = sids;
+ closure.num = num;
+
+ tdb_traverse(tdb, collect_aliasmem, &closure);
+ return NT_STATUS_OK;
+}
+
+ NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+{
+ NTSTATUS result;
+ DOM_SID *sids;
+ size_t i, num;
+ BOOL found = False;
+ char *member_string;
+ TDB_DATA kbuf, dbuf;
+ pstring key;
+ fstring sid_string;
+
+ result = alias_memberships(member, 1, &sids, &num);
+
+ if (!NT_STATUS_IS_OK(result))
+ return result;
+
+ for (i=0; i<num; i++) {
+ if (sid_compare(&sids[i], alias) == 0) {
+ found = True;
+ break;
+ }
+ }
+
+ if (!found) {
+ SAFE_FREE(sids);
+ return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+ }
+
+ if (i < num)
+ sids[i] = sids[num-1];
+
+ num -= 1;
+
+ sid_to_string(sid_string, member);
+ slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, sid_string);
+
+ kbuf.dsize = strlen(key)+1;
+ kbuf.dptr = key;
+
+ if (num == 0)
+ return tdb_delete(tdb, kbuf) == 0 ?
+ NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ member_string = SMB_STRDUP("");
+
+ if (member_string == NULL) {
+ SAFE_FREE(sids);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num; i++) {
+ char *s = member_string;
+
+ sid_to_string(sid_string, &sids[i]);
+ asprintf(&member_string, "%s %s", s, sid_string);
+
+ SAFE_FREE(s);
+ if (member_string == NULL) {
+ SAFE_FREE(sids);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ dbuf.dsize = strlen(member_string)+1;
+ dbuf.dptr = member_string;
+
+ result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ SAFE_FREE(sids);
+ SAFE_FREE(member_string);
+
+ return result;
+}
+
diff --git a/source/include/ads.h b/source/include/ads.h
index 0ef84b48058..29df0d2f353 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -1,3 +1,5 @@
+#ifndef _INCLUDE_ADS_H_
+#define _INCLUDE_ADS_H_
/*
header for ads (active directory) library routines
@@ -13,7 +15,11 @@ enum wb_posix_mapping {
};
typedef struct {
+#ifdef HAVE_LDAP
+ LDAP *ld;
+#else
void *ld; /* the active ldap structure */
+#endif
struct in_addr ldap_ip; /* the ip of the active connection, if any */
time_t last_attempt; /* last attempt to reconnect */
int ldap_port;
@@ -36,29 +42,35 @@ typedef struct {
char *kdc_server;
unsigned flags;
int time_offset;
- time_t expire;
+ time_t tgt_expire;
+ time_t tgs_expire;
time_t renewable;
} auth;
/* info derived from the servers config */
struct {
+ uint32 flags; /* cldap flags identifying the services. */
char *realm;
char *bind_path;
char *ldap_server_name;
+ char *server_site_name;
+ char *client_site_name;
time_t current_time;
+ int tried_closest_dc;
} config;
+} ADS_STRUCT;
- /* info derived from the servers schema */
- struct {
- enum wb_posix_mapping map_type;
- char *posix_homedir_attr;
- char *posix_shell_attr;
- char *posix_uidnumber_attr;
- char *posix_gidnumber_attr;
- char *posix_gecos_attr;
- } schema;
+/* used to remember the names of the posix attributes in AD */
+/* see the rfc2307 & sfu nss backends */
+
+struct posix_schema {
+ char *posix_homedir_attr;
+ char *posix_shell_attr;
+ char *posix_uidnumber_attr;
+ char *posix_gidnumber_attr;
+ char *posix_gecos_attr;
+};
-} ADS_STRUCT;
/* there are 5 possible types of errors the ads subsystem can produce */
enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS,
@@ -309,3 +321,4 @@ typedef struct {
int val;
int critical;
} ads_control;
+#endif
diff --git a/source/include/ads_cldap.h b/source/include/ads_cldap.h
index 65feb072e0f..fd227c895db 100644
--- a/source/include/ads_cldap.h
+++ b/source/include/ads_cldap.h
@@ -19,6 +19,9 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#ifndef _INCLUDE_ADS_CLDAP_H_
+#define _INCLUDE_ADS_CLDAP_H_
+
#define MAX_DNS_LABEL 255 + 1
struct cldap_netlogon_reply {
@@ -35,8 +38,8 @@ struct cldap_netlogon_reply {
char unk[MAX_DNS_LABEL];
char user_name[MAX_DNS_LABEL];
- char site_name[MAX_DNS_LABEL];
- char site_name_2[MAX_DNS_LABEL];
+ char server_site_name[MAX_DNS_LABEL];
+ char client_site_name[MAX_DNS_LABEL];
uint32 version;
uint16 lmnt_token;
@@ -55,4 +58,4 @@ struct cldap_netlogon_reply {
#define ADS_GOOD_TIMESERV 0x00000200 /* DC has hardware clock (and running time) */
#define ADS_NDNC 0x00000400 /* DomainName is non-domain NC serviced by LDAP server */
-
+#endif /* _INCLUDE_CLDAP_H_ */
diff --git a/source/include/ads_dns.h b/source/include/ads_dns.h
index fed886523f1..6c3430e21b0 100644
--- a/source/include/ads_dns.h
+++ b/source/include/ads_dns.h
@@ -48,8 +48,14 @@ struct dns_rr_srv {
uint16 weight;
uint16 port;
size_t num_ips;
- struct in_addr *ips; /* support multi-homed hosts */
+ struct in_addr *ips; /* support multi-homed hosts */
+};
+
+/* NS records */
+struct dns_rr_ns {
+ const char *hostname;
+ struct in_addr ip;
};
diff --git a/source/include/ads_protos.h b/source/include/ads_protos.h
new file mode 100644
index 00000000000..b5f323774d3
--- /dev/null
+++ b/source/include/ads_protos.h
@@ -0,0 +1,95 @@
+/*
+ * Prototypes for ads
+ */
+
+void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg);
+char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg);
+char *ads_get_dn_canonical(ADS_STRUCT *ads, LDAPMessage *msg);
+
+char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
+ const char *field);
+char **ads_pull_strings(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ size_t *num_values);
+char **ads_pull_strings_range(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ char **current_strings,
+ const char **next_attribute,
+ size_t *num_strings,
+ BOOL *more_strings);
+BOOL ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ uint32 *v);
+BOOL ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid);
+BOOL ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ DOM_SID *sid);
+int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, DOM_SID **sids);
+BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, SEC_DESC **sd);
+char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg);
+int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids);
+
+ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *machine);
+ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *printer,
+ const char *servername);
+ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res);
+ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *user);
+
+ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_search(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs);
+ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn, const char **attrs);
+ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res);
+ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path,
+ int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res);
+ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res);
+ADS_STATUS ads_search_retry(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs);
+ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs);
+ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs,
+ enum ads_extended_dn_flags flags);
+ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, LDAPMessage **res,
+ const DOM_SID *sid,
+ const char **attrs);
+
+
+LDAPMessage *ads_first_entry(ADS_STRUCT *ads, LDAPMessage *res);
+LDAPMessage *ads_next_entry(ADS_STRUCT *ads, LDAPMessage *res);
+void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
+ BOOL(*fn)(char *, void **, void *),
+ void *data_area);
+void ads_dump(ADS_STRUCT *ads, LDAPMessage *res);
+
+ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *res,
+ const char *gpo_dn,
+ struct GROUP_POLICY_OBJECT *gpo);
diff --git a/source/include/adt_tree.h b/source/include/adt_tree.h
index 51b6fb1c88b..a053013a9bc 100644
--- a/source/include/adt_tree.h
+++ b/source/include/adt_tree.h
@@ -21,9 +21,9 @@
#ifndef ADT_TREE_H
#define ADT_TREE_H
-#ifndef _BOOL
+#ifndef _UPPER_BOOL
typedef int BOOL;
-#define _BOOL
+#define _UPPER_BOOL
#endif
diff --git a/source/include/charset.h b/source/include/charset.h
index c5d03a62e89..5ac8d17486f 100644
--- a/source/include/charset.h
+++ b/source/include/charset.h
@@ -20,9 +20,9 @@
*/
/* this defines the charset types used in samba */
-typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t;
+typedef enum {CH_UTF16LE=0, CH_UTF16=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4, CH_UTF16BE=5} charset_t;
-#define NUM_CHARSETS 5
+#define NUM_CHARSETS 6
/*
* for each charset we have a function that pushes from that charset to a ucs2
@@ -119,6 +119,7 @@ static size_t CHARSETNAME ## _pull(void *cd, const char **inbuf, size_t *inbytes
struct charset_functions CHARSETNAME ## _functions = \
{#CHARSETNAME, CHARSETNAME ## _pull, CHARSETNAME ## _push}; \
\
+NTSTATUS charset_ ## CHARSETNAME ## _init(void); \
NTSTATUS charset_ ## CHARSETNAME ## _init(void) \
{ \
return smb_register_charset(& CHARSETNAME ## _functions); \
diff --git a/source/include/client.h b/source/include/client.h
index c6d7b162fcd..dc266995c62 100644
--- a/source/include/client.h
+++ b/source/include/client.h
@@ -41,9 +41,9 @@ typedef struct file_info
uid_t uid;
gid_t gid;
/* these times are normally kept in GMT */
- time_t mtime;
- time_t atime;
- time_t ctime;
+ struct timespec mtime_ts;
+ struct timespec atime_ts;
+ struct timespec ctime_ts;
pstring name;
pstring dir;
char short_name[13*3]; /* the *3 is to cope with multi-byte */
@@ -171,14 +171,10 @@ struct cli_state {
BOOL force_dos_errors;
BOOL case_sensitive; /* False by default. */
-
- /* was this structure allocated by cli_initialise? If so, then
- free in cli_shutdown() */
- BOOL allocated;
};
#define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001
#define CLI_FULL_CONNECTION_USE_KERBEROS 0x0002
-#define CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK 0x0004
+#define CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK 0x0004
#endif /* _CLIENT_H */
diff --git a/source/include/core.h b/source/include/core.h
new file mode 100644
index 00000000000..1f9ddb8b3c5
--- /dev/null
+++ b/source/include/core.h
@@ -0,0 +1,3 @@
+/* dummy file to deal with pidl autogenerated ndr files */
+
+#include "nterr.h"
diff --git a/source/include/core/nterr.h b/source/include/core/nterr.h
new file mode 100644
index 00000000000..c56735e7723
--- /dev/null
+++ b/source/include/core/nterr.h
@@ -0,0 +1 @@
+#include "includes.h"
diff --git a/source/include/dcerpc.h b/source/include/dcerpc.h
new file mode 100644
index 00000000000..d7652628944
--- /dev/null
+++ b/source/include/dcerpc.h
@@ -0,0 +1,40 @@
+/* unused. Stub to make the pidl generated NDR parsers compile */
+
+/*
+ this is used to find pointers to calls
+*/
+struct dcerpc_interface_call {
+ const char *name;
+ size_t struct_size;
+ ndr_push_flags_fn_t ndr_push;
+ ndr_pull_flags_fn_t ndr_pull;
+ ndr_print_function_t ndr_print;
+ BOOL async;
+};
+
+struct dcerpc_endpoint_list {
+ uint32_t count;
+ const char * const *names;
+};
+
+struct dcerpc_authservice_list {
+ uint32_t count;
+ const char * const *names;
+};
+
+struct dcerpc_interface_table {
+ const char *name;
+ struct dcerpc_syntax_id syntax_id;
+ const char *helpstring;
+ uint32_t num_calls;
+ const struct dcerpc_interface_call *calls;
+ const struct dcerpc_endpoint_list *endpoints;
+ const struct dcerpc_authservice_list *authservices;
+};
+
+struct dcerpc_interface_list {
+ struct dcerpc_interface_list *prev, *next;
+ const struct dcerpc_interface_table *table;
+};
+
+
diff --git a/source/include/dlinklist.h b/source/include/dlinklist.h
index daec7640e40..e590bc3e7ee 100644
--- a/source/include/dlinklist.h
+++ b/source/include/dlinklist.h
@@ -21,10 +21,13 @@
/* To use these macros you must have a structure containing a next and
prev pointer */
+#ifndef _DLINKLIST_H
+#define _DLINKLIST_H
+
/* hook into the front of the list */
#define DLIST_ADD(list, p) \
-{ \
+do { \
if (!(list)) { \
(list) = (p); \
(p)->next = (p)->prev = NULL; \
@@ -34,11 +37,11 @@
(p)->prev = NULL; \
(list) = (p); \
}\
-}
+} while (0)
/* remove an element from a list - element doesn't have to be in list. */
#define DLIST_REMOVE(list, p) \
-{ \
+do { \
if ((p) == (list)) { \
(list) = (p)->next; \
if (list) (list)->prev = NULL; \
@@ -47,28 +50,29 @@
if ((p)->next) (p)->next->prev = (p)->prev; \
} \
if ((p) != (list)) (p)->next = (p)->prev = NULL; \
-}
+} while (0)
/* promote an element to the top of the list */
#define DLIST_PROMOTE(list, p) \
-{ \
- DLIST_REMOVE(list, p) \
- DLIST_ADD(list, p) \
-}
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD(list, p); \
+} while (0)
-/* hook into the end of the list - needs a tmp pointer */
-#define DLIST_ADD_END(list, p, tmp) \
-{ \
+/* hook into the end of the list - needs the entry type */
+#define DLIST_ADD_END(list, p, type) \
+do { \
if (!(list)) { \
(list) = (p); \
(p)->next = (p)->prev = NULL; \
} else { \
- for ((tmp) = (list); (tmp)->next; (tmp) = (tmp)->next) ; \
- (tmp)->next = (p); \
+ type tmp; \
+ for (tmp = (list); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (p); \
(p)->next = NULL; \
- (p)->prev = (tmp); \
+ (p)->prev = tmp; \
} \
-}
+} while (0)
/* insert 'p' after the given element 'el' in a list. If el is NULL then
this is the same as a DLIST_ADD() */
@@ -84,9 +88,27 @@ do { \
}\
} while (0)
-/* demote an element to the top of the list, needs a tmp pointer */
+/* demote an element to the end of the list, needs a tmp pointer */
#define DLIST_DEMOTE(list, p, tmp) \
-{ \
- DLIST_REMOVE(list, p) \
- DLIST_ADD_END(list, p, tmp) \
-}
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD_END(list, p, tmp); \
+} while (0)
+
+/* concatenate two lists - putting all elements of the 2nd list at the
+ end of the first list */
+#define DLIST_CONCATENATE(list1, list2, type) \
+do { \
+ if (!(list1)) { \
+ (list1) = (list2); \
+ } else { \
+ type tmp; \
+ for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (list2); \
+ if (list2) { \
+ (list2)->prev = tmp; \
+ } \
+ } \
+} while (0)
+
+#endif /* _DLINKLIST_H */
diff --git a/source/include/event.h b/source/include/event.h
index fdb990678db..ce687eca6d6 100644
--- a/source/include/event.h
+++ b/source/include/event.h
@@ -19,13 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-struct timed_event {
- struct timed_event *next, *prev;
- struct timeval when;
- const char *event_name;
- void (*handler)(struct timed_event *te,
- const struct timeval *now,
- void *private_data);
- void *private_data;
-};
+/* bits for file descriptor event flags */
+#define EVENT_FD_READ 1
+#define EVENT_FD_WRITE 2
diff --git a/source/include/gpo.h b/source/include/gpo.h
index 65c96c31e6b..c3ae20dd20b 100644
--- a/source/include/gpo.h
+++ b/source/include/gpo.h
@@ -20,11 +20,11 @@
enum GPO_LINK_TYPE {
- GP_LINK_UNKOWN,
- GP_LINK_MACHINE,
- GP_LINK_SITE,
- GP_LINK_DOMAIN,
- GP_LINK_OU
+ GP_LINK_UNKOWN = 0,
+ GP_LINK_MACHINE = 1,
+ GP_LINK_SITE = 2,
+ GP_LINK_DOMAIN = 3,
+ GP_LINK_OU = 4
};
/* GPO_OPTIONS */
@@ -35,11 +35,12 @@ enum GPO_LINK_TYPE {
#define GPO_LIST_FLAG_MACHINE 0x00000001
#define GPO_LIST_FLAG_SITEONLY 0x00000002
+#define GPO_VERSION_USER(x) (x >> 16)
+#define GPO_VERSION_MACHINE(x) (x & 0xffff)
+
struct GROUP_POLICY_OBJECT {
uint32 options; /* GPFLAGS_* */
uint32 version;
- uint16 version_user;
- uint16 version_machine;
const char *ds_path;
const char *file_sys_path;
const char *display_name;
@@ -62,8 +63,8 @@ struct GROUP_POLICY_OBJECT {
/* 'gPOptions', maybe a bitmask as well */
enum GPO_INHERIT {
- GPOPTIONS_INHERIT,
- GPOPTIONS_BLOCK_INHERITANCE
+ GPOPTIONS_INHERIT = 0,
+ GPOPTIONS_BLOCK_INHERITANCE = 1
};
/* 'flags' in a 'groupPolicyContainer' object */
@@ -89,3 +90,6 @@ struct GP_EXT {
char **snapins;
char **snapins_guid;
};
+
+#define GPO_CACHE_DIR "gpo_cache"
+#define GPT_INI "GPT.INI"
diff --git a/source/include/idmap.h b/source/include/idmap.h
index 474982f2926..80bd541a23f 100644
--- a/source/include/idmap.h
+++ b/source/include/idmap.h
@@ -24,37 +24,56 @@
Boston, MA 02111-1307, USA.
*/
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
+/* idmap version determines auto-conversion - this is the database
+ structure version specifier. */
-#define SMB_IDMAP_INTERFACE_VERSION 2
+#define IDMAP_VERSION 2
+/* The interface version specifier.
+ Updated to 3 for enum types by JRA. */
-#define ID_EMPTY 0x00
-#define ID_USERID 0x01
-#define ID_GROUPID 0x02
-#define ID_OTHER 0x04
+/* Updated to 4, completely new interface, SSS */
-#define ID_TYPEMASK 0x0f
+#define SMB_IDMAP_INTERFACE_VERSION 4
-#define ID_QUERY_ONLY 0x10
-#define ID_CACHE_ONLY 0x20
+struct idmap_domain {
+ const char *name;
+ BOOL default_domain;
+ BOOL readonly;
+ void *private_data;
+ struct idmap_methods *methods;
+};
/* Filled out by IDMAP backends */
struct idmap_methods {
/* Called when backend is first loaded */
- NTSTATUS (*init)( char *params );
+ NTSTATUS (*init)(struct idmap_domain *dom, const char *compat_params);
+
+ NTSTATUS (*unixids_to_sids)(struct idmap_domain *dom, struct id_map **ids);
+ NTSTATUS (*sids_to_unixids)(struct idmap_domain *dom, struct id_map **ids);
+ NTSTATUS (*set_mapping)(struct idmap_domain *dom, const struct id_map *map);
+ NTSTATUS (*remove_mapping)(struct idmap_domain *dom, const struct id_map *map);
- NTSTATUS (*allocate_id)(unid_t *id, int id_type);
- NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
- NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
- NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, int id_type);
+ /* Called to dump backends data */
+ /* NOTE: caller must use talloc_free to free maps when done */
+ NTSTATUS (*dump_data)(struct idmap_domain *dom, struct id_map **maps, int *num_maps);
/* Called when backend is unloaded */
- NTSTATUS (*close_fn)(void);
+ NTSTATUS (*close_fn)(struct idmap_domain *dom);
+};
+
+struct idmap_alloc_methods {
- /* Called to dump backend status */
- void (*status)(void);
+ /* Called when backend is first loaded */
+ NTSTATUS (*init)(const char *compat_params);
+
+ NTSTATUS (*allocate_id)(struct unixid *id);
+ NTSTATUS (*get_id_hwm)(struct unixid *id);
+ NTSTATUS (*set_id_hwm)(struct unixid *id);
+
+ /* Called when backend is unloaded */
+ NTSTATUS (*close_fn)(void);
};
+
#endif /* _IDMAP_H_ */
diff --git a/source/include/includes.h b/source/include/includes.h
index 0d456a7ce48..34b9c36c8ac 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -26,9 +26,15 @@
#undef SIZEOF_LONG
#endif
+#include "lib/replace/replace.h"
+
+/* make sure we have included the correct config.h */
#ifndef NO_CONFIG_H /* for some tests */
-#include "config.h"
+#ifndef CONFIG_H_IS_FROM_SAMBA
+#error "make sure you have removed all config.h files from standalone builds!"
+#error "the included config.h isn't from samba!"
#endif
+#endif /* NO_CONFIG_H */
/* only do the C++ reserved word check when we compile
to include --with-developer since too many systems
@@ -66,14 +72,12 @@
#undef HAVE_TERMIOS_H
#endif
-#if (__GNUC__ >= 3 ) && (__GNUC_MINOR__ >= 1 )
-/** Use gcc attribute to check printf fns. a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#ifndef _PUBLIC_
+#ifdef HAVE_VISIBILITY_ATTR
+# define _PUBLIC_ __attribute__((visibility("default")))
#else
-#define PRINTF_ATTRIBUTE(a1, a2)
+# define _PUBLIC_
+#endif
#endif
#if defined(__GNUC__) && !defined(__cplusplus)
@@ -95,281 +99,22 @@
#endif
#endif /* RELIANTUNIX */
-#include <sys/types.h>
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_UNIXSOCKET
-#include <sys/un.h>
-#endif
-
-#ifdef HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#elif HAVE_SYSCALL_H
-#include <syscall.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#else
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#endif
-
-#include <sys/stat.h>
-
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>
-#endif
-
-#include <signal.h>
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_SYS_PRIV_H
-#include <sys/priv.h>
-#endif
-#ifdef HAVE_SYS_ID_H
-#include <sys/id.h>
-#endif
-
-#include <errno.h>
-
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef HAVE_SYS_MODE_H
-/* apparently AIX needs this for S_ISLNK */
-#ifndef S_ISLNK
-#include <sys/mode.h>
-#endif
-#endif
-
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#endif
-
-#include <pwd.h>
-
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#else
-#ifdef HAVE_SYS_SYSLOG_H
-#include <sys/syslog.h>
-#endif
-#endif
-
-#include <sys/file.h>
-
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-
-/*
- * The next three defines are needed to access the IPTOS_* options
- * on some systems.
- */
-
-#ifdef HAVE_NETINET_IN_SYSTM_H
-#include <netinet/in_systm.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_IP_H
-#include <netinet/in_ip.h>
-#endif
-
-#ifdef HAVE_NETINET_IP_H
-#include <netinet/ip.h>
-#endif
-
-#if defined(HAVE_TERMIOS_H)
-/* POSIX terminal handling. */
-#include <termios.h>
-#elif defined(HAVE_TERMIO_H)
-/* Older SYSV terminal handling - don't use if we can avoid it. */
-#include <termio.h>
-#elif defined(HAVE_SYS_TERMIO_H)
-/* Older SYSV terminal handling - don't use if we can avoid it. */
-#include <sys/termio.h>
-#endif
-
-#if HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-
-#ifdef HAVE_SYS_VFS_H
-#include <sys/vfs.h>
-#endif
-
-#ifdef HAVE_SYS_ACL_H
-#include <sys/acl.h>
-#endif
-
-#ifdef HAVE_SYS_FS_S5PARAM_H
-#include <sys/fs/s5param.h>
-#endif
-
-#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY)
-#include <sys/filsys.h>
-#endif
-
-#ifdef HAVE_SYS_STATFS_H
-# include <sys/statfs.h>
-#endif
-
-#ifdef HAVE_DUSTAT_H
-#include <sys/dustat.h>
-#endif
-
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-
-#ifdef HAVE_SHADOW_H
-/*
- * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
- * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
- * them again without checking if they already exsist. This generates
- * two "Redefinition of macro" warnings for every single .c file that is
- * compiled.
- */
-#if defined(HPUX) && defined(TCP_NODELAY)
-#undef TCP_NODELAY
-#endif
-#if defined(HPUX) && defined(TCP_MAXSEG)
-#undef TCP_MAXSEG
-#endif
-#include <shadow.h>
-#endif
-
-#ifdef HAVE_GETPWANAM
-#include <sys/label.h>
-#include <sys/audit.h>
-#include <pwdadj.h>
-#endif
-
-#ifdef HAVE_SYS_SECURITY_H
-#include <sys/security.h>
-#include <prot.h>
-#define PASSWORD_LENGTH 16
-#endif /* HAVE_SYS_SECURITY_H */
-
-#ifdef HAVE_STROPTS_H
-#include <stropts.h>
-#endif
-
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
+#include "system/capability.h"
+#include "system/dir.h"
+#include "system/filesys.h"
+#include "system/glob.h"
+#include "system/iconv.h"
+#include "system/locale.h"
+#include "system/network.h"
+#include "system/passwd.h"
+#include "system/printing.h"
+#include "system/readline.h"
+#include "system/select.h"
+#include "system/shmem.h"
+#include "system/syslog.h"
+#include "system/terminal.h"
+#include "system/time.h"
+#include "system/wait.h"
#if defined(HAVE_RPC_RPC_H)
/*
@@ -420,26 +165,6 @@
#endif
#endif /* HAVE_NETGROUP */
-#if defined(HAVE_SYS_IPC_H)
-#include <sys/ipc.h>
-#endif /* HAVE_SYS_IPC_H */
-
-#if defined(HAVE_SYS_SHM_H)
-#include <sys/shm.h>
-#endif /* HAVE_SYS_SHM_H */
-
-#ifdef HAVE_NATIVE_ICONV
-#ifdef HAVE_ICONV
-#include <iconv.h>
-#endif
-#ifdef HAVE_GICONV
-#include <giconv.h>
-#endif
-#ifdef HAVE_BICONV
-#include <biconv.h>
-#endif
-#endif
-
#if HAVE_KRB5_H
#include <krb5.h>
#else
@@ -510,10 +235,6 @@
#include <sys/uio.h>
#endif
-#if HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
#if HAVE_LANGINFO_H
#include <langinfo.h>
#endif
@@ -881,13 +602,9 @@ struct timespec {
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
-#ifndef HAVE_STRERROR
-extern char *sys_errlist[];
-#define strerror(i) sys_errlist[i]
-#endif
-
-#ifndef HAVE_ERRNO_DECL
-extern int errno;
+#ifndef _UPPER_BOOL
+typedef int BOOL;
+#define _UPPER_BOOL
#endif
#ifdef HAVE_BROKEN_GETGROUPS
@@ -900,11 +617,6 @@ extern int errno;
#define NGROUPS_MAX 32 /* Guess... */
#endif
-#ifdef SOCKET_WRAPPER
-#define SOCKET_WRAPPER_REPLACE
-#include "include/socket_wrapper.h"
-#endif
-
/* Our own pstrings and fstrings */
#include "pstring.h"
@@ -912,17 +624,18 @@ extern int errno;
#include "xfile.h"
#include "intl.h"
#include "dlinklist.h"
-#include "tdb/tdb.h"
-#include "tdb/spinlock.h"
-#include "tdb/tdbutil.h"
+#include "tdb.h"
+#include "util_tdb.h"
+#include "tdbback.h"
-#include "talloc.h"
+#include "lib/talloc/talloc.h"
/* And a little extension. Abort on type mismatch */
#define talloc_get_type_abort(ptr, type) \
(type *)talloc_check_name_abort(ptr, #type)
#include "nt_status.h"
#include "ads.h"
+#include "gpo.h"
#include "ads_dns.h"
#include "interfaces.h"
#include "trans2.h"
@@ -935,6 +648,7 @@ extern int errno;
#include "debugparse.h"
#include "version.h"
#include "privileges.h"
+#include "locking.h"
#include "smb.h"
#include "ads_cldap.h"
#include "nameserv.h"
@@ -962,7 +676,6 @@ extern int errno;
#include "rpc_reg.h"
#include "rpc_samr.h"
#include "rpc_srvsvc.h"
-#include "rpc_wkssvc.h"
#include "rpc_spoolss.h"
#include "rpc_eventlog.h"
#include "rpc_dfs.h"
@@ -971,14 +684,11 @@ extern int errno;
#include "rpc_shutdown.h"
#include "rpc_perfcount.h"
#include "rpc_perfcount_defs.h"
+#include "librpc/gen_ndr/notify.h"
#include "nt_printing.h"
#include "idmap.h"
#include "client.h"
-#ifdef WITH_SMBWRAPPER
-#include "smbw.h"
-#endif
-
#include "session.h"
#include "asn_1.h"
#include "popt.h"
@@ -1062,11 +772,17 @@ enum flush_reason_enum {
/* NUM_FLUSH_REASONS must remain the last value in the enumeration. */
NUM_FLUSH_REASONS};
+#include "nss_info.h"
+
/***** automatically generated prototypes *****/
#ifndef NO_PROTO_H
#include "proto.h"
#endif
+#ifdef HAVE_LDAP
+#include "ads_protos.h"
+#endif
+
/* We need this after proto.h to reference GetTimeOfDay(). */
#include "smbprofile.h"
@@ -1128,10 +844,6 @@ enum flush_reason_enum {
#define PASSWORD_LENGTH 8
#endif
-#ifdef REPLACE_INET_NTOA
-#define inet_ntoa rep_inet_ntoa
-#endif
-
#ifndef HAVE_PIPE
#define SYNC_DNS 1
#endif
@@ -1160,58 +872,6 @@ enum flush_reason_enum {
#define ULTRIX_AUTH 1
#endif
-#ifndef HAVE_STRDUP
-char *strdup(const char *s);
-#endif
-
-#ifndef HAVE_STRNDUP
-char *strndup(const char *s, size_t size);
-#endif
-
-#ifndef HAVE_MEMMOVE
-void *memmove(void *dest,const void *src,int size);
-#endif
-
-#ifndef HAVE_INITGROUPS
-int initgroups(char *name,gid_t id);
-#endif
-
-#ifndef HAVE_RENAME
-int rename(const char *zfrom, const char *zto);
-#endif
-
-#ifndef HAVE_MKTIME
-time_t mktime(struct tm *t);
-#endif
-
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *d, const char *s, size_t bufsize);
-#endif
-
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *d, const char *s, size_t bufsize);
-#endif
-
-#ifndef HAVE_FTRUNCATE
-int ftruncate(int f,long l);
-#endif
-
-#ifndef HAVE_STRNDUP
-char *strndup(const char *s, size_t n);
-#endif
-
-#ifndef HAVE_STRNLEN
-size_t strnlen(const char *s, size_t n);
-#endif
-
-#ifndef HAVE_STRTOUL
-unsigned long strtoul(const char *nptr, char **endptr, int base);
-#endif
-
-#ifndef HAVE_SETENV
-int setenv(const char *name, const char *value, int overwrite);
-#endif
-
#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESUID_DECL))
/* stupid glibc */
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
@@ -1219,13 +879,6 @@ int setresuid(uid_t ruid, uid_t euid, uid_t suid);
#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESGID_DECL))
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
#endif
-#ifndef HAVE_VASPRINTF_DECL
-int vasprintf(char **ptr, const char *format, va_list ap);
-#endif
-
-#ifdef REPLACE_GETPASS
-#define getpass(prompt) getsmbpass((prompt))
-#endif
/*
* Some older systems seem not to have MAXHOSTNAMELEN
@@ -1255,12 +908,6 @@ int vasprintf(char **ptr, const char *format, va_list ap);
#define DEFAULT_SOCKET_OPTIONS ""
#endif
-/* Load header file for dynamic linking stuff */
-
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
/* dmalloc -- free heap debugger (dmalloc.org). This should be near
* the *bottom* of include files so as not to conflict. */
#ifdef ENABLE_DMALLOC
@@ -1399,28 +1046,6 @@ int fdprintf(int , const char *, ...) PRINTF_ATTRIBUTE(2,3);
int d_printf(const char *, ...) PRINTF_ATTRIBUTE(1,2);
/*PRINTFLIKE2 */
int d_fprintf(FILE *f, const char *, ...) PRINTF_ATTRIBUTE(2,3);
-#ifndef HAVE_SNPRINTF_DECL
-/*PRINTFLIKE3 */
-int snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4);
-#endif
-#ifndef HAVE_ASPRINTF_DECL
-/*PRINTFLIKE2 */
-int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
-#endif
-
-/* Fix prototype problem with non-C99 compliant snprintf implementations, esp
- HPUX 11. Don't change the sense of this #if statement. Read the comments
- in lib/snprint.c if you think you need to. See also bugzilla bug 174. */
-
-#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
-#define snprintf smb_snprintf
-#define vsnprintf smb_vsnprintf
-
-/* PRINTFLIKE3 */
-int smb_snprintf(char *str,size_t count,const char *fmt,...);
-int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args);
-
-#endif
/* PRINTFLIKE2 */
void sys_adminlog(int priority, const char *format_str, ...) PRINTF_ATTRIBUTE(2,3);
@@ -1450,14 +1075,6 @@ int smb_xvasprintf(char **ptr, const char *format, va_list ap) PRINTF_ATTRIBUTE(
#endif
#endif
-#ifndef HAVE_VSYSLOG
-void vsyslog (int facility_priority, const char *format, va_list arglist);
-#endif
-
-#ifndef HAVE_TIMEGM
-time_t timegm(struct tm *tm);
-#endif
-
/*
* Veritas File System. Often in addition to native.
* Quotas different.
@@ -1492,6 +1109,14 @@ krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_con
void krb5_free_unparsed_name(krb5_context ctx, char *val);
#endif
+/* Stub out initialize_krb5_error_table since it is not present in all
+ * Kerberos implementations. If it's not present, it's not necessary to
+ * call it.
+ */
+#ifndef HAVE_INITIALIZE_KRB5_ERROR_TABLE
+#define initialize_krb5_error_table()
+#endif
+
/* Samba wrapper function for krb5 functionality. */
void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
@@ -1500,7 +1125,6 @@ BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_tick
krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
-void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote);
krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, krb5_principal host_princ, int enctype);
@@ -1544,7 +1168,7 @@ BOOL smb_krb5_principal_compare_any_realm(krb5_context context,
krb5_const_principal princ1,
krb5_const_principal princ2);
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
- DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname);
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname, time_t *tgs_expire);
PAC_LOGON_INFO *get_logon_info_from_pac(PAC_DATA *pac_data);
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, const char *client_string, const char *service_string, time_t *new_start_time);
krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code);
@@ -1555,6 +1179,8 @@ krb5_error_code nt_status_to_krb5(NTSTATUS nt_status);
void smb_krb5_free_error(krb5_context context, krb5_error *krberror);
krb5_error_code handle_krberror_packet(krb5_context context,
krb5_data *packet);
+void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt);
+krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt);
#endif /* HAVE_KRB5 */
diff --git a/source/include/libmsrpc.h b/source/include/libmsrpc.h
index 36bae441775..7b28d313336 100644
--- a/source/include/libmsrpc.h
+++ b/source/include/libmsrpc.h
@@ -704,7 +704,7 @@ struct LsaQueryInfoPolicy {
char *forest_name;
/**remote server's domain guid*/
- struct uuid *domain_guid;
+ struct GUID *domain_guid;
/**remote server's domain SID*/
DOM_SID *domain_sid;
diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h
index 5aca12554f3..41f72d5fb3d 100644
--- a/source/include/libsmb_internal.h
+++ b/source/include/libsmb_internal.h
@@ -10,7 +10,7 @@
struct _SMBCSRV {
- struct cli_state cli;
+ struct cli_state *cli;
dev_t dev;
BOOL no_pathinfo;
BOOL no_pathinfo2;
@@ -81,6 +81,21 @@ struct smbc_internal_data {
BOOL _debug_stderr;
/*
+ * Support "Create Time" in get/set with the *xattr() functions, if
+ * true. This replaces the dos attribute strings C_TIME, A_TIME and
+ * M_TIME with CHANGE_TIME, ACCESS_TIME and WRITE_TIME, and adds
+ * CREATE_TIME. Default is FALSE, i.e. to use the old-style shorter
+ * names and to not support CREATE time, for backward compatibility.
+ */
+ BOOL _full_time_names;
+
+ /*
+ * The share mode of a file being opened. To match POSIX semantics
+ * (and maintain backward compatibility), DENY_NONE is the default.
+ */
+ smbc_share_mode _share_mode;
+
+ /*
* Authentication function which includes the context. This will be
* used if set; otherwise context->callbacks.auth_fn() will be used.
*/
diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h
index ba92259f701..45f2a41b088 100644
--- a/source/include/libsmbclient.h
+++ b/source/include/libsmbclient.h
@@ -141,6 +141,20 @@ struct smbc_dirent
#define SMBC_DOS_MODE_DIRECTORY 0x10
#define SMBC_DOS_MODE_ARCHIVE 0x20
+/*
+ * Valid values for the option "open_share_mode", when calling
+ * smbc_option_set()
+ */
+typedef enum smbc_share_mode
+{
+ SMBC_SHAREMODE_DENY_DOS = 0,
+ SMBC_SHAREMODE_DENY_ALL = 1,
+ SMBC_SHAREMODE_DENY_WRITE = 2,
+ SMBC_SHAREMODE_DENY_READ = 3,
+ SMBC_SHAREMODE_DENY_NONE = 4,
+ SMBC_SHAREMODE_DENY_FCB = 7
+} smbc_share_mode;
+
#ifndef ENOATTR
# define ENOATTR ENOENT /* No such attribute */
@@ -635,7 +649,7 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx);
void
smbc_option_set(SMBCCTX *context,
char *option_name,
- void *option_value);
+ ... /* option_value */);
/*
* Retrieve the current value of an option
*
diff --git a/source/include/local.h b/source/include/local.h
index fb931976362..6d32f4fe6e9 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -247,4 +247,7 @@
/* Default hash size for the winbindd cache. */
#define WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE 5000
+/* Windows minimum lock resolution timeout in ms */
+#define WINDOWS_MINIMUM_LOCK_TIMEOUT_MS 200
+
#endif
diff --git a/source/include/locking.h b/source/include/locking.h
new file mode 100644
index 00000000000..4b3b10d7367
--- /dev/null
+++ b/source/include/locking.h
@@ -0,0 +1,89 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB parameters and setup, plus a whole lot more.
+
+ Copyright (C) Jeremy Allison 2006
+
+ 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 _LOCKING_H
+#define _LOCKING_H
+
+/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb
+ and is used in calculating POSIX unlock ranges only. We differentiate between
+ PENDING read and write locks to allow posix lock downgrades to trigger a lock
+ re-evaluation. */
+
+enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_READ_LOCK, PENDING_WRITE_LOCK, UNLOCK_LOCK};
+enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
+
+#define IS_PENDING_LOCK(type) ((type) == PENDING_READ_LOCK || (type) == PENDING_WRITE_LOCK)
+
+/* This contains elements that differentiate locks. The smbpid is a
+ client supplied pid, and is essentially the locking context for
+ this client */
+
+struct lock_context {
+ uint32 smbpid;
+ uint16 tid;
+ struct process_id pid;
+};
+
+/* The key used in the brlock database. */
+
+struct lock_key {
+ SMB_DEV_T device;
+ SMB_INO_T inode;
+};
+
+struct files_struct;
+
+struct byte_range_lock {
+ struct files_struct *fsp;
+ unsigned int num_locks;
+ BOOL modified;
+ BOOL read_only;
+ struct lock_key key;
+ void *lock_data;
+};
+
+#define BRLOCK_FN_CAST() \
+ void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
+ enum brl_type lock_type, \
+ enum brl_flavour lock_flav, \
+ br_off start, br_off size)
+
+#define BRLOCK_FN(fn) \
+ void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
+ enum brl_type lock_type, \
+ enum brl_flavour lock_flav, \
+ br_off start, br_off size)
+
+/* Internal structure in brlock.tdb.
+ The data in brlock records is an unsorted linear array of these
+ records. It is unnecessary to store the count as tdb provides the
+ size of the record */
+
+struct lock_struct {
+ struct lock_context context;
+ br_off start;
+ br_off size;
+ uint16 fnum;
+ enum brl_type lock_type;
+ enum brl_flavour lock_flav;
+};
+
+#endif /* _LOCKING_H_ */
diff --git a/source/include/mangle.h b/source/include/mangle.h
index 2bdef4ad646..3d19ef9ed4f 100644
--- a/source/include/mangle.h
+++ b/source/include/mangle.h
@@ -6,9 +6,13 @@
struct mangle_fns {
void (*reset)(void);
- BOOL (*is_mangled)(const char *s, int snum);
- BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum);
- BOOL (*check_cache)(char *s, size_t maxlen, int snum);
- void (*name_map)(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum);
+ BOOL (*is_mangled)(const char *s, const struct share_params *p);
+ BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards,
+ const struct share_params *p);
+ BOOL (*check_cache)(char *s, size_t maxlen,
+ const struct share_params *p);
+ void (*name_map)(char *OutName, BOOL need83, BOOL cache83,
+ int default_case,
+ const struct share_params *p);
};
#endif /* _MANGLE_H_ */
diff --git a/source/include/mapping.h b/source/include/mapping.h
index fdaa2b04532..8ba784e98c8 100644
--- a/source/include/mapping.h
+++ b/source/include/mapping.h
@@ -26,7 +26,7 @@ typedef struct _GROUP_MAP {
struct pdb_methods *methods;
gid_t gid;
DOM_SID sid;
- enum SID_NAME_USE sid_name_use;
+ enum lsa_SidType sid_name_use;
fstring nt_name;
fstring comment;
} GROUP_MAP;
diff --git a/source/include/messages.h b/source/include/messages.h
index e246123ea9f..7cd0e023487 100644
--- a/source/include/messages.h
+++ b/source/include/messages.h
@@ -70,6 +70,13 @@
#define MSG_SMB_KERNEL_BREAK 3010
#define MSG_SMB_FILE_RENAME 3011
#define MSG_SMB_INJECT_FAULT 3012
+#define MSG_SMB_BLOCKING_LOCK_CANCEL 3013
+#define MSG_SMB_NOTIFY 3014
+#define MSG_SMB_STAT_CACHE_DELETE 3015
+/*
+ * Samba4 compatibility
+ */
+#define MSG_PVFS_NOTIFY 3016
/* winbind messages */
#define MSG_WINBIND_FINISHED 4001
@@ -77,6 +84,8 @@
#define MSG_WINBIND_ONLINE 4003
#define MSG_WINBIND_OFFLINE 4004
#define MSG_WINBIND_ONLINESTATUS 4005
+#define MSG_WINBIND_TRY_TO_GO_ONLINE 4006
+#define MSG_WINBIND_FAILED_TO_GO_ONLINE 4007
/* Flags to classify messages - used in message_send_all() */
/* Sender will filter by flag. */
@@ -91,4 +100,12 @@ struct process_id {
pid_t pid;
};
+/*
+ * Samba4 API compatibility layer
+ */
+
+struct server_id {
+ struct process_id id;
+};
+
#endif
diff --git a/source/include/msdfs.h b/source/include/msdfs.h
index e9fef5430ed..4e3487de0f4 100644
--- a/source/include/msdfs.h
+++ b/source/include/msdfs.h
@@ -71,6 +71,12 @@ struct dfs_path {
return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \
ERRSRV, ERRbadpath);; }
+#define RESOLVE_DFSPATH_STATUS(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)) \
+ return NT_STATUS_PATH_NOT_COVERED;; }
+
#define RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf) \
{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \
lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \
diff --git a/source/include/ndr.h b/source/include/ndr.h
new file mode 100644
index 00000000000..a416866ef25
--- /dev/null
+++ b/source/include/ndr.h
@@ -0,0 +1 @@
+/* dummy file to deal with pidl autogenerated ndr files */
diff --git a/source/include/nss_info.h b/source/include/nss_info.h
new file mode 100644
index 00000000000..50e5e8182a1
--- /dev/null
+++ b/source/include/nss_info.h
@@ -0,0 +1,92 @@
+/*
+ Unix SMB/CIFS implementation.
+ Idmap NSS headers
+
+ Copyright (C) Gerald Carter 2006
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _IDMAP_NSS_H
+#define _IDMAP_NSS_H
+
+#ifndef HAVE_LDAP
+# ifndef LDAPMessage
+# define LDAPMessage void
+# endif
+#endif
+
+/* The interface version specifier */
+
+#define SMB_NSS_INFO_INTERFACE_VERSION 1
+
+/* List of available backends. All backends must
+ register themselves */
+
+struct nss_function_entry {
+ struct nss_function_entry *prev, *next;
+
+ const char *name;
+ struct nss_info_methods *methods;
+};
+
+/* List of configured domains. Each domain points
+ back to its configured backend. */
+
+struct nss_domain_entry {
+ struct nss_domain_entry *prev, *next;
+
+ const char *domain;
+
+ NTSTATUS init_status;
+ struct nss_function_entry *backend;
+
+ /* hold state on a per domain basis */
+
+ void *state;
+};
+
+/* API */
+
+struct nss_info_methods {
+ NTSTATUS (*init)( struct nss_domain_entry *e );
+ NTSTATUS (*get_nss_info)( struct nss_domain_entry *e,
+ const DOM_SID *sid,
+ TALLOC_CTX *ctx,
+ ADS_STRUCT *ads, LDAPMessage *msg,
+ char **homedir, char **shell, char **gecos, gid_t *p_gid);
+ NTSTATUS (*close_fn)( void );
+};
+
+
+/* The following definitions come from nsswitch/nss_info.c */
+
+NTSTATUS smb_register_idmap_nss(int version,
+ const char *name,
+ struct nss_info_methods *methods);
+
+NTSTATUS nss_init( const char **nss_list );
+
+NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid,
+ TALLOC_CTX *ctx,
+ ADS_STRUCT *ads, LDAPMessage *msg,
+ char **homedir, char **shell, char **gecos,
+ gid_t *p_gid);
+
+NTSTATUS nss_close( const char *parameters );
+
+#endif /* _IDMAP_NSS_H_ */
+
diff --git a/source/include/nt_status.h b/source/include/nt_status.h
index 14c83eba4b3..471ac47927a 100644
--- a/source/include/nt_status.h
+++ b/source/include/nt_status.h
@@ -45,9 +45,9 @@ typedef uint32 NTSTATUS;
#endif
#if defined(HAVE_IMMEDIATE_STRUCTURES)
-typedef struct {uint32 v;} WERROR;
+typedef struct {uint32 w;} WERROR;
#define W_ERROR(x) ((WERROR) { x })
-#define W_ERROR_V(x) ((x).v)
+#define W_ERROR_V(x) ((x).w)
#else
typedef uint32 WERROR;
#define W_ERROR(x) (x)
@@ -56,7 +56,6 @@ 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))
@@ -67,4 +66,39 @@ typedef uint32 WERROR;
}\
} while (0)
+#define NT_STATUS_NOT_OK_RETURN(x) do { \
+ if (!NT_STATUS_IS_OK(x)) {\
+ return x;\
+ }\
+} while (0)
+
+/* The top byte in an NTSTATUS code is used as a type field.
+ * Windows only uses value 0xC0 as an indicator for an NT error
+ * and 0x00 for success.
+ * So we can use the type field to store other types of error codes
+ * inside the three lower bytes.
+ * NB: The system error codes (errno) are not integrated via a type of
+ * their own but are mapped to genuine NT error codes via
+ * map_nt_error_from_unix() */
+
+#define NT_STATUS_TYPE(status) ((NT_STATUS_V(status) & 0xFF000000) >> 24)
+
+#define NT_STATUS_TYPE_DOS 0xF1
+#define NT_STATUS_TYPE_LDAP 0xF2
+
+/* this defines special NTSTATUS codes to represent DOS errors. I
+ have chosen this macro to produce status codes in the invalid
+ NTSTATUS range */
+#define NT_STATUS_DOS_MASK (NT_STATUS_TYPE_DOS << 24)
+#define NT_STATUS_DOS(class, code) NT_STATUS(NT_STATUS_DOS_MASK | ((class)<<16) | code)
+#define NT_STATUS_IS_DOS(status) ((NT_STATUS_V(status) & 0xFF000000) == NT_STATUS_DOS_MASK)
+#define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF)
+#define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF)
+
+/* define ldap error codes as NTSTATUS codes */
+#define NT_STATUS_LDAP_MASK (NT_STATUS_TYPE_LDAP << 24)
+#define NT_STATUS_LDAP(code) NT_STATUS(NT_STATUS_LDAP_MASK | code)
+#define NT_STATUS_IS_LDAP(status) ((NT_STATUS_V(status) & 0xFF000000) == NT_STATUS_LDAP_MASK)
+#define NT_STATUS_LDAP_CODE(status) (NT_STATUS_V(status) & ~0xFF000000)
+
#endif
diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h
index c27ec3675b4..6d8c4e62c65 100644
--- a/source/include/ntdomain.h
+++ b/source/include/ntdomain.h
@@ -267,6 +267,12 @@ typedef struct pipes_struct {
BOOL bad_handle_fault_state;
/*
+ * Set to true when the backend does not support a call.
+ */
+
+ BOOL rng_fault_state;
+
+ /*
* Set to RPC_BIG_ENDIAN when dealing with big-endian PDU's
*/
diff --git a/source/include/nterr.h b/source/include/nterr.h
index 417719625e7..913ea5799e3 100644
--- a/source/include/nterr.h
+++ b/source/include/nterr.h
@@ -37,9 +37,6 @@
#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. */
@@ -562,7 +559,9 @@
#define NT_STATUS_TOO_MANY_LINKS NT_STATUS(0xC0000000 | 0x0265)
#define NT_STATUS_QUOTA_LIST_INCONSISTENT NT_STATUS(0xC0000000 | 0x0266)
#define NT_STATUS_FILE_IS_OFFLINE NT_STATUS(0xC0000000 | 0x0267)
+#define NT_STATUS_DS_NO_MORE_RIDS NT_STATUS(0xC0000000 | 0x02a8)
#define NT_STATUS_NOT_A_REPARSE_POINT NT_STATUS(0xC0000000 | 0x0275)
#define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */
+#define NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED NT_STATUS(0xC0000000 | 0x20004)
#endif /* _NTERR_H */
diff --git a/source/include/ntlmssp.h b/source/include/ntlmssp.h
index a2dac7dc0ba..d15ce18021c 100644
--- a/source/include/ntlmssp.h
+++ b/source/include/ntlmssp.h
@@ -65,6 +65,10 @@ enum NTLM_MESSAGE_TYPE
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000
+#define NTLMSSP_FEATURE_SESSION_KEY 0x00000001
+#define NTLMSSP_FEATURE_SIGN 0x00000002
+#define NTLMSSP_FEATURE_SEAL 0x00000004
+
#define NTLMSSP_NAME_TYPE_SERVER 0x01
#define NTLMSSP_NAME_TYPE_DOMAIN 0x02
#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03
@@ -85,7 +89,8 @@ typedef struct ntlmssp_state
char *user;
char *domain;
char *workstation;
- char *password;
+ unsigned char *nt_hash;
+ unsigned char *lm_hash;
char *server_domain;
DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 432976412db..10f77e1ed51 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -34,8 +34,8 @@
#define ACCT_FULL_NAME 0x00000002
#define ACCT_RID 0x00000004
#define ACCT_PRIMARY_GID 0x00000008
-#define ACCT_ADMIN_DESC 0x00000010
-#define ACCT_DESCRIPTION 0x00000020
+#define ACCT_DESCRIPTION 0x00000010
+#define ACCT_COMMENT 0x00000020
#define ACCT_HOME_DIR 0x00000040
#define ACCT_HOME_DRIVE 0x00000080
#define ACCT_LOGON_SCRIPT 0x00000100
@@ -90,7 +90,7 @@ enum pdb_elements {
PDB_UNIXHOMEDIR,
PDB_ACCTDESC,
PDB_WORKSTATIONS,
- PDB_UNKNOWNSTR,
+ PDB_COMMENT,
PDB_MUNGEDDIAL,
PDB_HOURS,
PDB_FIELDS_PRESENT,
@@ -160,7 +160,7 @@ struct samu {
const char *profile_path; /* profile path string */
const char *acct_desc; /* user description string */
const char *workstations; /* login from workstations string */
- const char *unknown_str; /* don't know what this is, yet. */
+ const char *comment;
const char *munged_dial; /* munged path name and dial-back tel number */
DOM_SID user_sid;
@@ -240,9 +240,11 @@ struct pdb_search {
* There's no point in allocating arrays in
* samr_lookup_rids twice. It was done in the srv_samr_nt.c code as well as in
* the pdb module. Remove the latter, this might happen more often. VL.
+ * changed to version 14 to move lookup_rids and lookup_names to return
+ * enum lsa_SidType rather than uint32.
*/
-#define PASSDB_INTERFACE_VERSION 13
+#define PASSDB_INTERFACE_VERSION 15
struct pdb_methods
{
@@ -298,7 +300,7 @@ struct pdb_methods
DOM_SID sid);
NTSTATUS (*enum_group_mapping)(struct pdb_methods *methods,
- const DOM_SID *sid, enum SID_NAME_USE sid_name_use,
+ const DOM_SID *sid, enum lsa_SidType sid_name_use,
GROUP_MAP **pp_rmap, size_t *p_num_entries,
BOOL unix_only);
@@ -363,14 +365,14 @@ struct pdb_methods
int num_rids,
uint32 *rids,
const char **pp_names,
- uint32 *attrs);
+ enum lsa_SidType *attrs);
NTSTATUS (*lookup_names)(struct pdb_methods *methods,
const DOM_SID *domain_sid,
int num_names,
const char **pp_names,
uint32 *rids,
- uint32 *attrs);
+ enum lsa_SidType *attrs);
NTSTATUS (*get_account_policy)(struct pdb_methods *methods,
int policy_index, uint32 *value);
@@ -391,10 +393,12 @@ struct pdb_methods
BOOL (*uid_to_rid)(struct pdb_methods *methods, uid_t uid,
uint32 *rid);
+ BOOL (*uid_to_sid)(struct pdb_methods *methods, uid_t uid,
+ DOM_SID *sid);
BOOL (*gid_to_sid)(struct pdb_methods *methods, gid_t gid,
DOM_SID *sid);
BOOL (*sid_to_id)(struct pdb_methods *methods, const DOM_SID *sid,
- union unid_t *id, enum SID_NAME_USE *type);
+ union unid_t *id, enum lsa_SidType *type);
BOOL (*rid_algorithm)(struct pdb_methods *methods);
BOOL (*new_rid)(struct pdb_methods *methods, uint32 *rid);
diff --git a/source/include/printing.h b/source/include/printing.h
index 54f32d5954c..21caff0a832 100644
--- a/source/include/printing.h
+++ b/source/include/printing.h
@@ -73,6 +73,10 @@ extern struct printif cups_printif;
extern struct printif iprint_printif;
#endif /* HAVE_IPRINT */
+#if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
+extern struct printif test_printif;
+#endif /* DEVELOPER||ENABLE_BUILD_FARM_HACKS */
+
/* PRINT_MAX_JOBID is now defined in local.h */
#define UNIX_JOB_START PRINT_MAX_JOBID
#define NEXT_JOBID(j) ((j+1) % PRINT_MAX_JOBID > 0 ? (j+1) % PRINT_MAX_JOBID : 1)
diff --git a/source/include/privileges.h b/source/include/privileges.h
index 3f425f6d728..eac42e0ba93 100644
--- a/source/include/privileges.h
+++ b/source/include/privileges.h
@@ -93,9 +93,9 @@ typedef struct {
uint32 attr;
} LUID_ATTR;
-#ifndef _BOOL
+#ifndef _UPPER_BOOL
typedef int BOOL;
-#define _BOOL /* So we don't typedef BOOL again in vfs.h */
+#define _UPPER_BOOL
#endif
typedef struct {
diff --git a/source/include/reg_objects.h b/source/include/reg_objects.h
index fff6fa16f79..1f819df999b 100644
--- a/source/include/reg_objects.h
+++ b/source/include/reg_objects.h
@@ -1,7 +1,8 @@
/*
- Unix SMB/CIFS implementation.
+ Samba's Internal Registry objects
+
SMB parameters and setup
- Copyright (C) Gerald Carter 2002-2005.
+ Copyright (C) Gerald Carter 2002-2006.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/source/include/rpc_client.h b/source/include/rpc_client.h
index 0524f037e2c..b05924e657d 100644
--- a/source/include/rpc_client.h
+++ b/source/include/rpc_client.h
@@ -21,6 +21,10 @@
#ifndef _RPC_CLIENT_H
#define _RPC_CLIENT_H
+/* autogenerated client stubs */
+
+#include "librpc/gen_ndr/cli_wkssvc.h"
+
/* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req() */
#define CLI_DO_RPC_INTERNAL( pcli, ctx, p_idx, opnum, q_in, r_out, \
diff --git a/source/include/rpc_dce.h b/source/include/rpc_dce.h
index b4d350ee6fa..09e5f25da8c 100644
--- a/source/include/rpc_dce.h
+++ b/source/include/rpc_dce.h
@@ -126,7 +126,7 @@ enum schannel_direction {
/* RPC_IFACE */
typedef struct rpc_iface_info {
- struct uuid uuid; /* 16 bytes of rpc interface identification */
+ struct GUID uuid; /* 16 bytes of rpc interface identification */
uint32 version; /* the interface version number */
} RPC_IFACE;
diff --git a/source/include/rpc_dfs.h b/source/include/rpc_dfs.h
index 9aba123deed..601d3d3b017 100644
--- a/source/include/rpc_dfs.h
+++ b/source/include/rpc_dfs.h
@@ -76,7 +76,7 @@ typedef struct netdfs_dfs_Info4 {
UNISTR2 comment;
uint32 state;
uint32 timeout;
- struct uuid guid;
+ struct GUID guid;
uint32 num_stores;
uint32 ptr0_stores;
uint32 size_stores;
diff --git a/source/include/rpc_ds.h b/source/include/rpc_ds.h
index 424e6c0494a..bfe5179490c 100644
--- a/source/include/rpc_ds.h
+++ b/source/include/rpc_ds.h
@@ -49,7 +49,7 @@
#define DSROLE_BDC 4
#define DSROLE_PDC 5
-/* Settings for the domainFunctionality attribteu in the rootDSE */
+/* Settings for the domainFunctionality attribute in the rootDSE */
#define DS_DOMAIN_FUNCTION_2000 0
#define DS_DOMAIN_FUCNTION_2003_MIXED 1
@@ -68,7 +68,7 @@ typedef struct
uint32 dnsname_ptr;
uint32 forestname_ptr;
- struct uuid domain_guid;
+ struct GUID domain_guid;
UNISTR2 netbios_domain;
@@ -114,7 +114,7 @@ typedef struct {
uint32 trust_type;
uint32 trust_attributes;
uint32 sid_ptr;
- struct uuid guid;
+ struct GUID guid;
UNISTR2 netbios_domain;
UNISTR2 dns_domain;
@@ -128,7 +128,7 @@ struct ds_domain_trust {
uint32 parent_index;
uint32 trust_type;
uint32 trust_attributes;
- struct uuid guid;
+ struct GUID guid;
DOM_SID sid;
char *netbios_domain;
diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h
index c4ce9e021d1..28dea219777 100644
--- a/source/include/rpc_lsa.h
+++ b/source/include/rpc_lsa.h
@@ -174,7 +174,7 @@ typedef struct lsa_dns_dom_info
UNIHDR hdr_dns_dom_name;
UNIHDR hdr_forest_name;
- struct uuid dom_guid; /* domain GUID */
+ struct GUID dom_guid; /* domain GUID */
UNISTR2 uni_nb_dom_name;
UNISTR2 uni_dns_dom_name;
diff --git a/source/include/rpc_misc.h b/source/include/rpc_misc.h
index 661d436859a..7404f5669d2 100644
--- a/source/include/rpc_misc.h
+++ b/source/include/rpc_misc.h
@@ -92,34 +92,16 @@ enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_
* RPC policy handle used pretty much everywhere
**********************************************************************/
+typedef struct policy_handle POLICY_HND;
typedef struct {
uint32 ptr_hnd; /* pointer to enumeration handle */
uint32 handle; /* enumeration handle */
} ENUM_HND;
-
-
-/**********************************************************************
- * RPC policy handle used pretty much everywhere
- **********************************************************************/
-
-typedef struct {
- 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;
+#define OUR_HANDLE(hnd) (((hnd)==NULL) ? "NULL" :\
+ ( IVAL((hnd)->uuid.node,2) == (uint32)sys_getpid() ? "OURS" : \
+ "OTHER")), ((unsigned int)IVAL((hnd)->uuid.node,2)),\
+ ((unsigned int)sys_getpid() )
/**********************************************************************
@@ -357,10 +339,5 @@ typedef struct owf_info {
uint8 data[16];
} OWF_INFO;
-typedef struct uint64_s
-{
- uint32 low;
- uint32 high;
-} UINT64_S;
#endif /* _RPC_MISC_H */
diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h
index 01b6b99cbf6..d2d5cf2fbb4 100644
--- a/source/include/rpc_netlogon.h
+++ b/source/include/rpc_netlogon.h
@@ -671,8 +671,8 @@ typedef struct account_lockout_string {
uint32 offset;
uint32 length;
/* uint16 *bindata; */
- UINT64_S lockout_duration;
- UINT64_S reset_count;
+ uint64 lockout_duration;
+ uint64 reset_count;
uint32 bad_attempt_lockout;
uint32 dummy;
} LOCKOUT_STRING;
@@ -689,12 +689,12 @@ typedef struct sam_domain_info_info {
UNIHDR hdr_dom_name;
UNIHDR hdr_oem_info;
- UINT64_S force_logoff;
+ uint64 force_logoff;
uint16 min_pwd_len;
uint16 pwd_history_len;
- UINT64_S max_pwd_age;
- UINT64_S min_pwd_age;
- UINT64_S dom_mod_count;
+ uint64 max_pwd_age;
+ uint64 min_pwd_age;
+ uint64 dom_mod_count;
NTTIME creation_time;
uint32 security_information;
@@ -858,7 +858,7 @@ typedef struct sam_alias_mem_info_info {
/* SAM_DELTA_POLICY (0x0D) */
typedef struct {
uint32 max_log_size; /* 0x5000 */
- UINT64_S audit_retention_period; /* 0 */
+ uint64 audit_retention_period; /* 0 */
uint32 auditing_mode; /* 0 */
uint32 num_events;
uint32 ptr_events;
@@ -870,7 +870,7 @@ typedef struct {
uint32 min_workset_size; /* 0x00010000 */
uint32 max_workset_size; /* 0x0f000000 */
uint32 page_file_limit; /* 0 */
- UINT64_S time_limit; /* 0 */
+ uint64 time_limit; /* 0 */
NTTIME modify_time; /* 0x3c*/
NTTIME create_time; /* a7080110 */
BUFHDR2 hdr_sec_desc;
@@ -917,7 +917,7 @@ typedef struct {
uint32 min_workset_size; /* 0x00010000 */
uint32 max_workset_size; /* 0x0f000000 */
uint32 page_file_limit; /* 0 */
- UINT64_S time_limit; /* 0 */
+ uint64 time_limit; /* 0 */
uint32 system_flags; /* 1 */
BUFHDR2 hdr_sec_desc;
@@ -971,7 +971,7 @@ typedef struct {
typedef struct {
uint32 seqnum;
uint32 dom_mod_count_ptr;
- UINT64_S dom_mod_count; /* domain mod count at last sync */
+ uint64 dom_mod_count; /* domain mod count at last sync */
} SAM_DELTA_MOD_COUNT;
typedef union sam_delta_ctr_info {
@@ -1013,7 +1013,7 @@ typedef struct net_q_sam_deltas_info {
DOM_CRED ret_creds;
uint32 database_id;
- UINT64_S dom_mod_count; /* domain mod count at last sync */
+ uint64 dom_mod_count; /* domain mod count at last sync */
uint32 max_size; /* preferred maximum length */
} NET_Q_SAM_DELTAS;
@@ -1022,7 +1022,7 @@ typedef struct net_q_sam_deltas_info {
typedef struct net_r_sam_deltas_info {
DOM_CRED srv_creds;
- UINT64_S dom_mod_count; /* new domain mod count */
+ uint64 dom_mod_count; /* new domain mod count */
uint32 ptr_deltas;
uint32 num_deltas;
@@ -1041,9 +1041,9 @@ typedef struct net_q_dsr_getdcname {
uint32 ptr_domain_name;
UNISTR2 uni_domain_name;
uint32 ptr_domain_guid;
- struct uuid *domain_guid;
+ struct GUID *domain_guid;
uint32 ptr_site_guid;
- struct uuid *site_guid;
+ struct GUID *site_guid;
uint32 flags;
} NET_Q_DSR_GETDCNAME;
@@ -1054,7 +1054,7 @@ typedef struct net_r_dsr_getdcname {
uint32 ptr_dc_address;
UNISTR2 uni_dc_address;
int32 dc_address_type;
- struct uuid domain_guid;
+ struct GUID domain_guid;
uint32 ptr_domain_name;
UNISTR2 uni_domain_name;
uint32 ptr_forest_name;
diff --git a/source/include/rpc_perfcount.h b/source/include/rpc_perfcount.h
index 0e3a6eb0181..eecc24148dd 100644
--- a/source/include/rpc_perfcount.h
+++ b/source/include/rpc_perfcount.h
@@ -1,5 +1,26 @@
#ifndef _RPC_PERFCOUNT_H
#define _RPC_PERFCOUNT_H
+/*
+ * Unix SMB/CIFS implementation.
+ * Virtual Windows Registry Layer
+ *
+ * Copyright (C) Marcin Krzysztof Porwit 2005,
+ * Copyright (C) Gerald (Jerry) Carter 2005.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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.
+ */
typedef struct perf_counter_definition
{
@@ -59,8 +80,8 @@ typedef struct perf_object_type
uint32 DefaultCounter;
uint32 NumInstances;
uint32 CodePage;
- UINT64_S PerfTime;
- UINT64_S PerfFreq;
+ uint64 PerfTime;
+ uint64 PerfFreq;
PERF_COUNTER_DEFINITION *counters;
PERF_INSTANCE_DEFINITION *instances;
PERF_COUNTER_BLOCK counter_data;
@@ -88,13 +109,13 @@ typedef struct perf_data_block
PerfTime, and having it there will make my offset math much easier. */
uint32 Padding;
/* Now when I'm marshalling this, I'll need to call prs_align_uint64()
- before I start encodint the UINT64_S structs */
+ before I start encodint the uint64 structs */
/* clock rate * seconds uptime */
- UINT64_S PerfTime;
+ uint64 PerfTime;
/* The clock rate of the CPU */
- UINT64_S PerfFreq;
+ uint64 PerfFreq;
/* used for high-res timers -- for now PerfTime * 10e7 */
- UINT64_S PerfTime100nSec;
+ uint64 PerfTime100nSec;
uint32 SystemNameLength;
uint32 SystemNameOffset;
/* The SystemName, in unicode, terminated */
diff --git a/source/include/rpc_perfcount_defs.h b/source/include/rpc_perfcount_defs.h
index 3999a6864d8..16d83c7b112 100644
--- a/source/include/rpc_perfcount_defs.h
+++ b/source/include/rpc_perfcount_defs.h
@@ -1,5 +1,26 @@
#ifndef _RPC_PERFCOUNT_DEFS_H
#define _RPC_PERFCOUNT_DEFS_H
+/*
+ * Unix SMB/CIFS implementation.
+ * Virtual Windows Registry Layer
+ *
+ * Copyright (C) Marcin Krzysztof Porwit 2005,
+ * Copyright (C) Gerald (Jerry) Carter 2005.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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.
+ */
/*
* The following #defines match what is in winperf.h.
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 910ccee1135..9a5484598a4 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -4,7 +4,7 @@
Copyright (C) Andrew Tridgell 1992-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Paul Ashton 1997-2000
- Copyright (C) Jean François Micouleau 1998-2001
+ Copyright (C) Jean François Micouleau 1998-2001
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
@@ -121,7 +121,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_QUERY_USERGROUPS 0x27
#define SAMR_QUERY_DISPINFO 0x28
-#define SAMR_UNKNOWN_29 0x29
+#define SAMR_GET_DISPENUM_INDEX 0x29
#define SAMR_UNKNOWN_2a 0x2a
#define SAMR_UNKNOWN_2b 0x2b
#define SAMR_GET_USRDOM_PWINFO 0x2c
@@ -174,7 +174,7 @@ typedef struct sam_user_info_23
UNIHDR hdr_profile_path; /* profile path unicode string header */
UNIHDR hdr_acct_desc ; /* user description */
UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
- UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+ UNIHDR hdr_comment;
UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
uint8 lm_pwd[16]; /* lm user passwords */
@@ -211,7 +211,7 @@ typedef struct sam_user_info_23
UNISTR2 uni_profile_path; /* profile path unicode string */
UNISTR2 uni_acct_desc ; /* user description unicode string */
UNISTR2 uni_workstations; /* login from workstations unicode string */
- UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+ UNISTR2 uni_comment;
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
LOGON_HRS logon_hrs;
@@ -222,7 +222,7 @@ typedef struct sam_user_info_23
typedef struct sam_user_info_24
{
uint8 pass[516];
- uint16 pw_len;
+ uint8 pw_len;
} SAM_USER_INFO_24;
/*
@@ -250,7 +250,7 @@ typedef struct sam_user_info_25
UNIHDR hdr_profile_path; /* profile path unicode string header */
UNIHDR hdr_acct_desc ; /* user description */
UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
- UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+ UNIHDR hdr_comment;
UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
uint8 lm_pwd[16]; /* lm user passwords */
@@ -274,7 +274,7 @@ typedef struct sam_user_info_25
UNISTR2 uni_profile_path; /* profile path unicode string */
UNISTR2 uni_acct_desc ; /* user description unicode string */
UNISTR2 uni_workstations; /* login from workstations unicode string */
- UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+ UNISTR2 uni_comment;
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
} SAM_USER_INFO_25;
@@ -304,7 +304,7 @@ typedef struct sam_user_info_21
UNIHDR hdr_profile_path; /* profile path unicode string header */
UNIHDR hdr_acct_desc ; /* user description */
UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
- UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+ UNIHDR hdr_comment;
UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
uint8 lm_pwd[16]; /* lm user passwords */
@@ -340,7 +340,7 @@ typedef struct sam_user_info_21
UNISTR2 uni_profile_path; /* profile path unicode string */
UNISTR2 uni_acct_desc ; /* user description unicode string */
UNISTR2 uni_workstations; /* login from workstations unicode string */
- UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+ UNISTR2 uni_comment;
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */
LOGON_HRS logon_hrs;
@@ -553,7 +553,7 @@ typedef struct sam_unknown_info_2_inf
pointer is referring to
*/
- UINT64_S seq_num;
+ uint64 seq_num;
uint32 unknown_4; /* 0x0000 0001 */
uint32 server_role;
@@ -605,7 +605,7 @@ typedef struct sam_unknown_info_7_info
typedef struct sam_unknown_info_8_info
{
- UINT64_S seq_num;
+ uint64 seq_num;
NTTIME domain_create_time;
} SAM_UNK_INFO_8;
@@ -626,7 +626,7 @@ typedef struct sam_unknown_info_12_inf
typedef struct sam_unknown_info_13_info
{
- UINT64_S seq_num;
+ uint64 seq_num;
NTTIME domain_create_time;
uint32 unknown1;
uint32 unknown2;
@@ -1047,6 +1047,22 @@ typedef struct r_samr_query_dispinfo_info
} SAMR_R_QUERY_DISPINFO;
+/* SAMR_Q_GET_DISPENUM_INDEX */
+typedef struct q_samr_get_dispenum_index
+{
+ POLICY_HND domain_pol;
+ uint16 switch_level;
+ LSA_STRING name;
+
+} SAMR_Q_GET_DISPENUM_INDEX;
+
+/* SAMR_R_GET_DISPENUM_INDEX */
+typedef struct r_samr_get_dispenum_index
+{
+ uint32 idx;
+ NTSTATUS status;
+
+} SAMR_R_GET_DISPENUM_INDEX;
/* SAMR_Q_DELETE_DOM_GROUP - delete domain group */
typedef struct q_samr_delete_dom_group_info
diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h
index c385e41fd30..9e65052f849 100644
--- a/source/include/rpc_secdes.h
+++ b/source/include/rpc_secdes.h
@@ -43,33 +43,6 @@
#define SEC_ACE_OBJECT_PRESENT 0x00000001 /* thanks for Jim McDonough <jmcd@us.ibm.com> */
#define SEC_ACE_OBJECT_INHERITED_PRESENT 0x00000002
-#define SEC_ACE_FLAG_OBJECT_INHERIT 0x1
-#define SEC_ACE_FLAG_CONTAINER_INHERIT 0x2
-#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x4
-#define SEC_ACE_FLAG_INHERIT_ONLY 0x8
-#define SEC_ACE_FLAG_INHERITED_ACE 0x10 /* New for Windows 2000 */
-#define SEC_ACE_FLAG_VALID_INHERIT 0xf
-#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
-#define SEC_ACE_FLAG_FAILED_ACCESS 0x80
-
-#define SEC_ACE_TYPE_ACCESS_ALLOWED 0x0
-#define SEC_ACE_TYPE_ACCESS_DENIED 0x1
-#define SEC_ACE_TYPE_SYSTEM_AUDIT 0x2
-#define SEC_ACE_TYPE_SYSTEM_ALARM 0x3
-#define SEC_ACE_TYPE_ALLOWED_COMPOUND 0x4
-#define SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT 0x5
-#define SEC_ACE_TYPE_ACCESS_DENIED_OBJECT 0x6
-#define SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT 0x7
-#define SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT 0x8
-
-#define SEC_DESC_OWNER_DEFAULTED 0x0001
-#define SEC_DESC_GROUP_DEFAULTED 0x0002
-#define SEC_DESC_DACL_PRESENT 0x0004
-#define SEC_DESC_DACL_DEFAULTED 0x0008
-#define SEC_DESC_SACL_PRESENT 0x0010
-#define SEC_DESC_SACL_DEFAULTED 0x0020
-#define SEC_DESC_DACL_TRUSTED 0x0040
-#define SEC_DESC_SERVER_SECURITY 0x0080
/*
* New Windows 2000 bits.
*/
@@ -80,11 +53,6 @@
#define SE_DESC_DACL_PROTECTED 0x1000
#define SE_DESC_SACL_PROTECTED 0x2000
-/* Don't know what this means. */
-#define SEC_DESC_RM_CONTROL_VALID 0x4000
-
-#define SEC_DESC_SELF_RELATIVE 0x8000
-
/* security information */
#define OWNER_SECURITY_INFORMATION 0x00000001
#define GROUP_SECURITY_INFORMATION 0x00000002
@@ -104,25 +72,20 @@
PROTECTED_DACL_SECURITY_INFORMATION)
/* SEC_ACCESS */
-typedef struct security_info_info
-{
- uint32 mask;
-
-} SEC_ACCESS;
+typedef uint32 SEC_ACCESS;
/* SEC_ACE */
-typedef struct security_ace_info
-{
+typedef struct security_ace_info {
uint8 type; /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */
uint8 flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */
uint16 size;
- SEC_ACCESS info;
+ SEC_ACCESS access_mask;
/* this stuff may be present when type is XXXX_TYPE_XXXX_OBJECT */
uint32 obj_flags; /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */
- struct uuid obj_guid; /* object GUID */
- struct uuid inh_guid; /* inherited object GUID */
+ struct GUID obj_guid; /* object GUID */
+ struct GUID inh_guid; /* inherited object GUID */
/* eof object stuff */
DOM_SID trustee;
@@ -134,19 +97,14 @@ typedef struct security_ace_info
#define ACL_REVISION 0x3
#endif
-#ifndef NT4_ACL_REVISION
-#define NT4_ACL_REVISION 0x2
-#endif
-
#ifndef _SEC_ACL
/* SEC_ACL */
-typedef struct security_acl_info
-{
+typedef struct security_acl_info {
uint16 revision; /* 0x0003 */
uint16 size; /* size in bytes of the entire ACL structure */
uint32 num_aces; /* number of Access Control Entries */
- SEC_ACE *ace;
+ SEC_ACE *aces;
} SEC_ACL;
#define SEC_ACL_HEADER_SIZE (2 * sizeof(uint16) + sizeof(uint32))
@@ -159,8 +117,7 @@ typedef struct security_acl_info
#ifndef _SEC_DESC
/* SEC_DESC */
-typedef struct security_descriptor_info
-{
+typedef struct security_descriptor_info {
uint16 revision; /* 0x0001 */
uint16 type; /* SEC_DESC_xxxx flags */
@@ -172,7 +129,7 @@ typedef struct security_descriptor_info
SEC_ACL *dacl; /* user ACL */
SEC_ACL *sacl; /* system ACL */
DOM_SID *owner_sid;
- DOM_SID *grp_sid;
+ DOM_SID *group_sid;
} SEC_DESC;
#define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16) + 4 * sizeof(uint32))
@@ -181,8 +138,7 @@ typedef struct security_descriptor_info
#ifndef _SEC_DESC_BUF
/* SEC_DESC_BUF */
-typedef struct sec_desc_buf_info
-{
+typedef struct sec_desc_buf_info {
uint32 max_len;
uint32 ptr;
uint32 len;
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index 681dcd73d42..069d2b3bf74 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -984,6 +984,12 @@ typedef struct printer_info_5
}
PRINTER_INFO_5;
+typedef struct printer_info_6
+{
+ uint32 status;
+}
+PRINTER_INFO_6;
+
#define SPOOL_DS_PUBLISH 1
#define SPOOL_DS_UPDATE 2
#define SPOOL_DS_UNPUBLISH 4
@@ -1556,7 +1562,7 @@ typedef struct {
uint32 previousnames_len;
uint32 previousnames_ptr;
NTTIME driverdate;
- UINT64_S driverversion;
+ uint64 driverversion;
uint32 dummy4;
uint32 mfgname_ptr;
uint32 oemurl_ptr;
diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h
index f84054b878b..5d32d65c3df 100644
--- a/source/include/rpc_srvsvc.h
+++ b/source/include/rpc_srvsvc.h
@@ -485,12 +485,6 @@ typedef struct ptr_info_1004_info
SH_INFO_1004_STR info_1004_str;
} SRV_SHARE_INFO_1004;
-#define SHARE_1005_IN_DFS 0x00000001
-#define SHARE_1005_DFS_ROOT 0x00000002
-/* use the CSC policy mask and shift to match up with the smb.conf parm */
-#define SHARE_1005_CSC_POLICY_MASK 0x00000030
-#define SHARE_1005_CSC_POLICY_SHIFT 4
-
typedef struct share_info_1005_info
{
uint32 share_info_flags;
diff --git a/source/include/rpc_wkssvc.h b/source/include/rpc_wkssvc.h
deleted file mode 100644
index adc37c255b2..00000000000
--- a/source/include/rpc_wkssvc.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- 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
-
- 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_WKS_H /* _RPC_WKS_H */
-#define _RPC_WKS_H
-
-
-/* wkssvc pipe */
-#define WKS_QUERY_INFO 0x00
-
-
-/* WKS_Q_QUERY_INFO - probably a capabilities request */
-typedef struct q_wks_query_info_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */
-
- uint16 switch_value; /* info level 100 (0x64) */
-
-} WKS_Q_QUERY_INFO;
-
-
-/* WKS_INFO_100 - level 100 info */
-typedef struct wks_info_100_info
-{
- uint32 platform_id; /* 0x0000 01f4 - unknown */
- uint32 ptr_compname; /* pointer to server name */
- uint32 ptr_lan_grp ; /* pointer to domain name */
- uint32 ver_major; /* 4 - unknown */
- uint32 ver_minor; /* 0 - unknown */
-
- UNISTR2 uni_compname; /* unicode server name */
- UNISTR2 uni_lan_grp ; /* unicode domain name */
-
-} WKS_INFO_100;
-
-
-/* WKS_R_QUERY_INFO - probably a capabilities request */
-typedef struct r_wks_query_info_info
-{
- uint16 switch_value; /* 100 (0x64) - switch value */
-
- /* for now, only level 100 is supported. this should be an enum container */
- uint32 ptr_1; /* pointer 1 */
- WKS_INFO_100 *wks100; /* workstation info level 100 */
-
- NTSTATUS status; /* return status */
-
-} WKS_R_QUERY_INFO;
-
-
-#endif /* _RPC_WKS_H */
-
diff --git a/source/include/session.h b/source/include/session.h
index f613afee09a..8c8faab5325 100644
--- a/source/include/session.h
+++ b/source/include/session.h
@@ -1,8 +1,10 @@
/*
Unix SMB/CIFS implementation.
session handling for recording currently vailid vuids
+
Copyright (C) tridge@samba.org 2001
Copyright (C) Andew Bartlett <abartlet@samba.org> 2001
+ Copyright (C) Gerald (Jerry) Carter 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -36,5 +38,6 @@ struct sessionid {
uint32 id_num;
uint32 pid;
fstring ip_addr;
+ time_t connect_start;
};
diff --git a/source/include/smb.h b/source/include/smb.h
index b805f864a04..3f0356f2248 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -28,7 +28,7 @@
#define _SMB_H
/* logged when starting the various Samba daemons */
-#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2006"
+#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2007"
#if defined(LARGE_SMB_OFF_T)
@@ -52,11 +52,6 @@
#define Auto (2)
#define Required (3)
-#ifndef _BOOL
-typedef int BOOL;
-#define _BOOL /* So we don't typedef BOOL again in vfs.h */
-#endif
-
#define SIZEOFWORD 2
#ifndef DEF_CREATE_MASK
@@ -138,13 +133,6 @@ typedef int BOOL;
#define OPENX_FILE_CREATE_IF_NOT_EXIST 0x10
#define OPENX_FILE_FAIL_IF_NOT_EXIST 0
-/* share types */
-#define STYPE_DISKTREE 0 /* Disk drive */
-#define STYPE_PRINTQ 1 /* Spooler queue */
-#define STYPE_DEVICE 2 /* Serial device */
-#define STYPE_IPC 3 /* Interprocess communication (IPC) */
-#define STYPE_HIDDEN 0x80000000 /* share is a hidden one (ends with $) */
-
#include "doserr.h"
typedef union unid_t {
@@ -179,6 +167,10 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
#define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((unsigned char *)(src))[0],\
((unsigned char *)(dest))[1] = ((unsigned char *)(src))[1], (dest))
+/* Large data type for manipulating uint32 unicode codepoints */
+typedef uint32 codepoint_t;
+#define INVALID_CODEPOINT ((codepoint_t)-1)
+
/* pipe string names */
#define PIPE_LANMAN "\\PIPE\\LANMAN"
#define PIPE_SRVSVC "\\PIPE\\srvsvc"
@@ -217,10 +209,7 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
#define PI_MAX_PIPES 14
/* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */
-typedef struct nttime_info {
- uint32 low;
- uint32 high;
-} NTTIME;
+typedef uint64_t NTTIME;
/* Allowable account control bits */
@@ -255,7 +244,7 @@ typedef struct nttime_info {
#define SID_MAX_SIZE ((size_t)(8+(MAXSUBAUTHS*4)))
/* SID Types */
-enum SID_NAME_USE {
+enum lsa_SidType {
SID_NAME_USE_NONE = 0,
SID_NAME_USER = 1, /* user */
SID_NAME_DOM_GRP, /* domain group */
@@ -280,7 +269,7 @@ enum SID_NAME_USE {
*
* @sa http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/accctrl_38yn.asp
**/
-typedef struct sid_info {
+typedef struct dom_sid {
uint8 sid_rev_num; /**< SID revision number */
uint8 num_auths; /**< Number of sub-authorities */
uint8 id_auth[6]; /**< Identifier Authority */
@@ -293,6 +282,36 @@ typedef struct sid_info {
uint32 sub_auths[MAXSUBAUTHS];
} DOM_SID;
+#define dom_sid2 dom_sid
+#define dom_sid28 dom_sid
+
+enum id_mapping {
+ ID_UNKNOWN,
+ ID_MAPPED,
+ ID_UNMAPPED
+};
+
+enum id_type {
+ ID_TYPE_UID,
+ ID_TYPE_GID
+};
+
+struct unixid {
+ uint32_t id;
+ enum id_type type;
+};
+
+struct id_map {
+ DOM_SID *sid;
+ struct unixid xid;
+ enum id_mapping status;
+};
+
+#include "librpc/ndr/misc.h"
+#include "librpc/ndr/security.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/wkssvc.h"
+
struct lsa_dom_info {
BOOL valid;
DOM_SID sid;
@@ -303,7 +322,7 @@ struct lsa_dom_info {
struct lsa_name_info {
uint32 rid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *name;
int dom_idx;
};
@@ -407,9 +426,60 @@ struct fd_handle {
unsigned long file_id;
};
+struct messaging_context;
+struct event_context;
+struct fd_event;
struct timed_event;
struct idle_event;
struct share_mode_entry;
+struct uuid;
+
+struct vfs_fsp_data {
+ struct vfs_fsp_data *next;
+ struct vfs_handle_struct *owner;
+ /* NOTE: This structure contains two pointers so that we can guarantee
+ * that the end of the structure is always both 4-byte and 8-byte aligned.
+ */
+};
+
+/* the basic packet size, assuming no words or bytes */
+#define smb_size 39
+
+struct notify_change {
+ uint32_t action;
+ const char *name;
+};
+
+struct notify_mid_map;
+struct notify_entry;
+struct notify_event;
+struct notify_change_request;
+struct sys_notify_backend;
+struct sys_notify_context {
+ struct event_context *ev;
+ struct connection_struct *conn;
+ void *private_data; /* For use by the system backend */
+};
+
+struct notify_change_buf {
+ /*
+ * If no requests are pending, changes are queued here. Simple array,
+ * we only append.
+ */
+
+ /*
+ * num_changes == -1 means that we have got a catch-all change, when
+ * asked we just return NT_STATUS_OK without specific changes.
+ */
+ int num_changes;
+ struct notify_change *changes;
+
+ /*
+ * If no changes are around requests are queued here. Using a linked
+ * list, because we have to append at the end and delete from the top.
+ */
+ struct notify_change_request *requests;
+};
typedef struct files_struct {
struct files_struct *next, *prev;
@@ -435,6 +505,7 @@ typedef struct files_struct {
int oplock_type;
int sent_oplock_break;
struct timed_event *oplock_timeout;
+ struct lock_struct last_lock_failure;
struct share_mode_entry *pending_break_messages;
int num_pending_break_messages;
@@ -448,8 +519,14 @@ typedef struct files_struct {
BOOL is_stat;
BOOL aio_write_behind;
BOOL lockdb_clean;
+ BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */
+ BOOL posix_open;
char *fsp_name;
+
+ struct vfs_fsp_data *vfs_extension;
FAKE_FILE_HANDLE *fake_file_handle;
+
+ struct notify_change_buf *notify;
} files_struct;
#include "ntquotas.h"
@@ -520,6 +597,8 @@ struct trans_state {
/* Include VFS stuff */
+struct security_descriptor_info;
+
#include "smb_acls.h"
#include "vfs.h"
@@ -533,11 +612,19 @@ struct dfree_cached_info {
struct dptr_struct;
+struct share_params {
+ int service;
+};
+
+struct share_iterator {
+ int next_id;
+};
+
typedef struct connection_struct {
struct connection_struct *next, *prev;
- TALLOC_CTX *mem_ctx;
+ TALLOC_CTX *mem_ctx; /* long-lived memory context for things hanging off this struct. */
unsigned cnum; /* an index passed over the wire */
- int service;
+ struct share_params *params;
BOOL force_user;
BOOL force_group;
struct vuid_cache vuid_cache;
@@ -584,6 +671,7 @@ typedef struct connection_struct {
name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */
struct dfree_cached_info *dfree_info;
struct trans_state *pending_trans;
+ struct notify_context *notify_ctx;
} connection_struct;
struct current_user {
@@ -656,6 +744,8 @@ struct pending_message_list {
DATA_BLOB private_data;
};
+#define SHARE_MODE_FLAG_POSIX_OPEN 0x1
+
/* struct returned by get_share_modes */
struct share_mode_entry {
struct process_id pid;
@@ -672,6 +762,7 @@ struct share_mode_entry {
SMB_INO_T inode;
unsigned long share_file_id;
uint32 uid; /* uid of file opener. */
+ uint16 flags; /* POSIX_OPEN only defined so far... */
};
/* oplock break message definition - linearization of share_mode_entry.
@@ -689,10 +780,11 @@ Offset Data length.
36 SMB_INO_T inode 8 bytes
44 unsigned long file_id 4 bytes
48 uint32 uid 4 bytes
-52
+52 uint16 flags 2 bytes
+54
*/
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 52
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 54
struct share_mode_lock {
const char *servicepath; /* canonicalized. */
@@ -703,7 +795,6 @@ struct share_mode_lock {
struct share_mode_entry *share_modes;
UNIX_USER_TOKEN *delete_token;
BOOL delete_on_close;
- BOOL initial_delete_on_close;
BOOL fresh;
BOOL modified;
};
@@ -718,7 +809,6 @@ struct locking_data {
struct {
int num_share_mode_entries;
BOOL delete_on_close;
- BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */
uint32 delete_token_size; /* Only valid if either of
the two previous fields
are True. */
@@ -733,6 +823,16 @@ struct locking_data {
*/
};
+/* Used to store pipe open records for NetFileEnum() */
+
+struct pipe_open_rec {
+ struct process_id pid;
+ uid_t uid;
+ int pnum;
+ fstring name;
+};
+
+
#define NT_HASH_LEN 16
#define LM_HASH_LEN 16
@@ -836,57 +936,11 @@ struct parm_struct {
#define FLAG_HIDE 0x2000 /* options that should be hidden in SWAT */
#define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
-/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb
- and is used in calculating POSIX unlock ranges only. */
-
-enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK};
-enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
-
-/* The key used in the brlock database. */
-
-struct lock_key {
- SMB_DEV_T device;
- SMB_INO_T inode;
-};
-
-struct byte_range_lock {
- files_struct *fsp;
- unsigned int num_locks;
- BOOL modified;
- struct lock_key key;
- void *lock_data;
-};
-
-#define BRLOCK_FN_CAST() \
- void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
- enum brl_type lock_type, \
- enum brl_flavour lock_flav, \
- br_off start, br_off size)
-
-#define BRLOCK_FN(fn) \
- void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
- enum brl_type lock_type, \
- enum brl_flavour lock_flav, \
- br_off start, br_off size)
-
-#define LOCKING_FN_CAST() \
- void (*)(struct share_mode_entry *, const char *, const char *)
-
-#define LOCKING_FN(fn) \
- void (*fn)(struct share_mode_entry *, const char *, const char *)
-
struct bitmap {
uint32 *b;
unsigned int n;
};
-#ifndef LOCKING_VERSION
-#define LOCKING_VERSION 4
-#endif /* LOCKING_VERSION */
-
-/* the basic packet size, assuming no words or bytes */
-#define smb_size 39
-
/* offsets into message for common items */
#define smb_com 8
#define smb_rcls 9
@@ -948,7 +1002,7 @@ struct bitmap {
#define SMBunlock 0x0D /* unlock byte range */
#define SMBctemp 0x0E /* create temporary file */
#define SMBmknew 0x0F /* make new file */
-#define SMBchkpth 0x10 /* check directory path */
+#define SMBcheckpath 0x10 /* check directory path */
#define SMBexit 0x11 /* process exit */
#define SMBlseek 0x12 /* seek */
#define SMBtcon 0x70 /* tree connect */
@@ -1337,7 +1391,7 @@ struct bitmap {
#define FILE_READ_ONLY_VOLUME 0x00080000
/* ChangeNotify flags. */
-#define FILE_NOTIFY_CHANGE_FILE 0x001
+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x001
#define FILE_NOTIFY_CHANGE_DIR_NAME 0x002
#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x004
#define FILE_NOTIFY_CHANGE_SIZE 0x008
@@ -1346,7 +1400,23 @@ struct bitmap {
#define FILE_NOTIFY_CHANGE_CREATION 0x040
#define FILE_NOTIFY_CHANGE_EA 0x080
#define FILE_NOTIFY_CHANGE_SECURITY 0x100
-#define FILE_NOTIFY_CHANGE_FILE_NAME 0x200
+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+
+#define FILE_NOTIFY_CHANGE_NAME \
+ (FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME)
+
+/* change notify action results */
+#define NOTIFY_ACTION_ADDED 1
+#define NOTIFY_ACTION_REMOVED 2
+#define NOTIFY_ACTION_MODIFIED 3
+#define NOTIFY_ACTION_OLD_NAME 4
+#define NOTIFY_ACTION_NEW_NAME 5
+#define NOTIFY_ACTION_ADDED_STREAM 6
+#define NOTIFY_ACTION_REMOVED_STREAM 7
+#define NOTIFY_ACTION_MODIFIED_STREAM 8
+
/* where to find the base of the SMB packet proper */
#define smb_base(buf) (((char *)(buf))+4)
@@ -1375,36 +1445,6 @@ char *strdup(char *s);
#define SELECT_CAST
#endif
-/* these are used in NetServerEnum to choose what to receive */
-#define SV_TYPE_WORKSTATION 0x00000001
-#define SV_TYPE_SERVER 0x00000002
-#define SV_TYPE_SQLSERVER 0x00000004
-#define SV_TYPE_DOMAIN_CTRL 0x00000008
-#define SV_TYPE_DOMAIN_BAKCTRL 0x00000010
-#define SV_TYPE_TIME_SOURCE 0x00000020
-#define SV_TYPE_AFP 0x00000040
-#define SV_TYPE_NOVELL 0x00000080
-#define SV_TYPE_DOMAIN_MEMBER 0x00000100
-#define SV_TYPE_PRINTQ_SERVER 0x00000200
-#define SV_TYPE_DIALIN_SERVER 0x00000400
-#define SV_TYPE_SERVER_UNIX 0x00000800
-#define SV_TYPE_NT 0x00001000
-#define SV_TYPE_WFW 0x00002000
-#define SV_TYPE_SERVER_MFPN 0x00004000
-#define SV_TYPE_SERVER_NT 0x00008000
-#define SV_TYPE_POTENTIAL_BROWSER 0x00010000
-#define SV_TYPE_BACKUP_BROWSER 0x00020000
-#define SV_TYPE_MASTER_BROWSER 0x00040000
-#define SV_TYPE_DOMAIN_MASTER 0x00080000
-#define SV_TYPE_SERVER_OSF 0x00100000
-#define SV_TYPE_SERVER_VMS 0x00200000
-#define SV_TYPE_WIN95_PLUS 0x00400000
-#define SV_TYPE_DFS_SERVER 0x00800000
-#define SV_TYPE_ALTERNATE_XPORT 0x20000000
-#define SV_TYPE_LOCAL_LIST_ONLY 0x40000000
-#define SV_TYPE_DOMAIN_ENUM 0x80000000
-#define SV_TYPE_ALL 0xFFFFFFFF
-
/* This was set by JHT in liaison with Jeremy Allison early 1997
* History:
* Version 4.0 - never made public
@@ -1436,6 +1476,7 @@ char *strdup(char *s);
#define FLAGS2_LONG_PATH_COMPONENTS 0x0001
#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002
#define FLAGS2_SMB_SECURITY_SIGNATURES 0x0004
+#define FLAGS2_UNKNOWN_BIT4 0x0010
#define FLAGS2_IS_LONG_NAME 0x0040
#define FLAGS2_EXTENDED_SECURITY 0x0800
#define FLAGS2_DFS_PATHNAMES 0x1000
@@ -1483,7 +1524,7 @@ enum server_types {
enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,
PRINT_QNX,PRINT_PLP,PRINT_LPRNG,PRINT_SOFTQ,
PRINT_CUPS,PRINT_LPRNT,PRINT_LPROS2,PRINT_IPRINT
-#ifdef DEVELOPER
+#if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
,PRINT_TEST,PRINT_VLP
#endif /* DEVELOPER */
};
@@ -1499,7 +1540,8 @@ enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, LDAP_PAS
/* Remote architectures we know about. */
enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
- RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_SAMBA, RA_CIFSFS};
+ RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_VISTA,
+ RA_SAMBA, RA_CIFSFS};
/* case handling */
enum case_handling {CASE_LOWER,CASE_UPPER};
@@ -1552,19 +1594,19 @@ extern int chain_size;
* Note these must fit into 16-bits.
*/
-#define NO_OPLOCK 0
-#define EXCLUSIVE_OPLOCK 1
-#define BATCH_OPLOCK 2
-#define LEVEL_II_OPLOCK 4
+#define NO_OPLOCK 0x0
+#define EXCLUSIVE_OPLOCK 0x1
+#define BATCH_OPLOCK 0x2
+#define LEVEL_II_OPLOCK 0x4
/* The following are Samba-private. */
-#define INTERNAL_OPEN_ONLY 8
-#define FAKE_LEVEL_II_OPLOCK 16 /* Client requested no_oplock, but we have to
+#define INTERNAL_OPEN_ONLY 0x8
+#define FAKE_LEVEL_II_OPLOCK 0x10 /* Client requested no_oplock, but we have to
* inform potential level2 holders on
* write. */
-#define DEFERRED_OPEN_ENTRY 32
-#define UNUSED_SHARE_MODE_ENTRY 64
-#define FORCE_OPLOCK_BREAK_TO_NONE 128
+#define DEFERRED_OPEN_ENTRY 0x20
+#define UNUSED_SHARE_MODE_ENTRY 0x40
+#define FORCE_OPLOCK_BREAK_TO_NONE 0x80
/* None of the following should ever appear in fsp->oplock_request. */
#define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY|DEFERRED_OPEN_ENTRY|UNUSED_SHARE_MODE_ENTRY|FORCE_OPLOCK_BREAK_TO_NONE)
@@ -1651,17 +1693,6 @@ struct kernel_oplocks {
int notification_fd;
};
-
-/* this structure defines the functions for doing change notify in
- various implementations */
-struct cnotify_fns {
- void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
- BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
- void (*remove_notify)(void *data);
- int select_time;
- int notification_fd;
-};
-
#include "smb_macros.h"
#define MAX_NETBIOSNAME_LEN 16
@@ -1697,6 +1728,15 @@ struct pwd_info {
fstring password;
};
+/* For split krb5 SPNEGO blobs. */
+struct pending_auth_data {
+ struct pending_auth_data *prev, *next;
+ uint16 vuid; /* Tag for this entry. */
+ uint16 smbpid; /* Alternate tag for this entry. */
+ size_t needed_len;
+ DATA_BLOB partial_data;
+};
+
typedef struct user_struct {
struct user_struct *next, *prev;
uint16 vuid; /* Tag for this entry. */
@@ -1726,7 +1766,6 @@ typedef struct user_struct {
struct auth_serversupplied_info *server_info;
struct auth_ntlmssp_state *auth_ntlmssp_state;
-
} user_struct;
struct unix_error_map {
@@ -1803,6 +1842,9 @@ struct ip_service {
unsigned port;
};
+/* Special name type used to cause a _kerberos DNS lookup. */
+#define KDC_NAME_TYPE 0xDCDC
+
/* Used by the SMB signing functions. */
typedef struct smb_sign_info {
@@ -1834,15 +1876,7 @@ struct ea_list {
/* EA to use for DOS attributes */
#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
-struct uuid {
- uint32 time_low;
- uint16 time_mid;
- uint16 time_hi_and_version;
- uint8 clock_seq[2];
- uint8 node[6];
-};
#define UUID_SIZE 16
-
#define UUID_FLAT_SIZE 16
typedef struct uuid_flat {
uint8 info[UUID_FLAT_SIZE];
diff --git a/source/include/smb_acls.h b/source/include/smb_acls.h
index ec1316e4667..0d2cbdde52c 100644
--- a/source/include/smb_acls.h
+++ b/source/include/smb_acls.h
@@ -20,250 +20,42 @@
#ifndef _SMB_ACLS_H
#define _SMB_ACLS_H
-#if defined(HAVE_POSIX_ACLS)
-/* This is an identity mapping (just remove the SMB_). */
-
-#define SMB_ACL_TAG_T acl_tag_t
-#define SMB_ACL_TYPE_T acl_type_t
-#define SMB_ACL_PERMSET_T acl_permset_t
-#define SMB_ACL_PERM_T acl_perm_t
-#define SMB_ACL_READ ACL_READ
-#define SMB_ACL_WRITE ACL_WRITE
-#define SMB_ACL_EXECUTE ACL_EXECUTE
-
-/* Types of ACLs. */
-#define SMB_ACL_USER ACL_USER
-#define SMB_ACL_USER_OBJ ACL_USER_OBJ
-#define SMB_ACL_GROUP ACL_GROUP
-#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
-#define SMB_ACL_OTHER ACL_OTHER
-#define SMB_ACL_MASK ACL_MASK
-
-#define SMB_ACL_T acl_t
-
-#define SMB_ACL_ENTRY_T acl_entry_t
-
-#define SMB_ACL_FIRST_ENTRY ACL_FIRST_ENTRY
-#define SMB_ACL_NEXT_ENTRY ACL_NEXT_ENTRY
-
-#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
-#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
-
-#elif defined(HAVE_TRU64_ACLS)
-
-/* This is for DEC/Compaq Tru64 UNIX */
-
-#define SMB_ACL_TAG_T acl_tag_t
-#define SMB_ACL_TYPE_T acl_type_t
-#define SMB_ACL_PERMSET_T acl_permset_t
-#define SMB_ACL_PERM_T acl_perm_t
-#define SMB_ACL_READ ACL_READ
-#define SMB_ACL_WRITE ACL_WRITE
-#define SMB_ACL_EXECUTE ACL_EXECUTE
-
-/* Types of ACLs. */
-#define SMB_ACL_USER ACL_USER
-#define SMB_ACL_USER_OBJ ACL_USER_OBJ
-#define SMB_ACL_GROUP ACL_GROUP
-#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
-#define SMB_ACL_OTHER ACL_OTHER
-#define SMB_ACL_MASK ACL_MASK
-
-#define SMB_ACL_T acl_t
-
-#define SMB_ACL_ENTRY_T acl_entry_t
-
-#define SMB_ACL_FIRST_ENTRY 0
-#define SMB_ACL_NEXT_ENTRY 1
-
-#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
-#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
-
-#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
-/*
- * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
- * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
- */
-
-/* SVR4.2 ES/MP ACLs */
-typedef int SMB_ACL_TAG_T;
typedef int SMB_ACL_TYPE_T;
-typedef ushort *SMB_ACL_PERMSET_T;
-typedef ushort SMB_ACL_PERM_T;
+typedef mode_t *SMB_ACL_PERMSET_T;
+typedef mode_t SMB_ACL_PERM_T;
#define SMB_ACL_READ 4
#define SMB_ACL_WRITE 2
#define SMB_ACL_EXECUTE 1
/* Types of ACLs. */
-#define SMB_ACL_USER USER
-#define SMB_ACL_USER_OBJ USER_OBJ
-#define SMB_ACL_GROUP GROUP
-#define SMB_ACL_GROUP_OBJ GROUP_OBJ
-#define SMB_ACL_OTHER OTHER_OBJ
-#define SMB_ACL_MASK CLASS_OBJ
-
-typedef struct SMB_ACL_T {
- int size;
- int count;
- int next;
- struct acl acl[1];
-} *SMB_ACL_T;
-
-typedef struct acl *SMB_ACL_ENTRY_T;
-
-#define SMB_ACL_FIRST_ENTRY 0
-#define SMB_ACL_NEXT_ENTRY 1
-
-#define SMB_ACL_TYPE_ACCESS 0
-#define SMB_ACL_TYPE_DEFAULT 1
-
-#elif defined(HAVE_HPUX_ACLS)
-
-/*
- * Based on the Solaris & UnixWare code.
- */
-
-#undef GROUP
-#include <sys/aclv.h>
+enum smb_acl_tag_t {
+ SMB_ACL_TAG_INVALID=0,
+ SMB_ACL_USER=1,
+ SMB_ACL_USER_OBJ,
+ SMB_ACL_GROUP,
+ SMB_ACL_GROUP_OBJ,
+ SMB_ACL_OTHER,
+ SMB_ACL_MASK
+};
-/* SVR4.2 ES/MP ACLs */
-typedef int SMB_ACL_TAG_T;
-typedef int SMB_ACL_TYPE_T;
-typedef ushort *SMB_ACL_PERMSET_T;
-typedef ushort SMB_ACL_PERM_T;
-#define SMB_ACL_READ 4
-#define SMB_ACL_WRITE 2
-#define SMB_ACL_EXECUTE 1
+typedef enum smb_acl_tag_t SMB_ACL_TAG_T;
-/* Types of ACLs. */
-#define SMB_ACL_USER USER
-#define SMB_ACL_USER_OBJ USER_OBJ
-#define SMB_ACL_GROUP GROUP
-#define SMB_ACL_GROUP_OBJ GROUP_OBJ
-#define SMB_ACL_OTHER OTHER_OBJ
-#define SMB_ACL_MASK CLASS_OBJ
+struct smb_acl_entry {
+ enum smb_acl_tag_t a_type;
+ SMB_ACL_PERM_T a_perm;
+ uid_t uid;
+ gid_t gid;
+};
-typedef struct SMB_ACL_T {
+typedef struct smb_acl_t {
int size;
int count;
int next;
- struct acl acl[1];
-} *SMB_ACL_T;
-
-typedef struct acl *SMB_ACL_ENTRY_T;
-
-#define SMB_ACL_FIRST_ENTRY 0
-#define SMB_ACL_NEXT_ENTRY 1
-
-#define SMB_ACL_TYPE_ACCESS 0
-#define SMB_ACL_TYPE_DEFAULT 1
-
-#elif defined(HAVE_IRIX_ACLS)
-
-#define SMB_ACL_TAG_T acl_tag_t
-#define SMB_ACL_TYPE_T acl_type_t
-#define SMB_ACL_PERMSET_T acl_permset_t
-#define SMB_ACL_PERM_T acl_perm_t
-#define SMB_ACL_READ ACL_READ
-#define SMB_ACL_WRITE ACL_WRITE
-#define SMB_ACL_EXECUTE ACL_EXECUTE
-
-/* Types of ACLs. */
-#define SMB_ACL_USER ACL_USER
-#define SMB_ACL_USER_OBJ ACL_USER_OBJ
-#define SMB_ACL_GROUP ACL_GROUP
-#define SMB_ACL_GROUP_OBJ ACL_GROUP_OBJ
-#define SMB_ACL_OTHER ACL_OTHER_OBJ
-#define SMB_ACL_MASK ACL_MASK
-
-typedef struct SMB_ACL_T {
- int next;
- BOOL freeaclp;
- struct acl *aclp;
-} *SMB_ACL_T;
-
-#define SMB_ACL_ENTRY_T acl_entry_t
-
-#define SMB_ACL_FIRST_ENTRY 0
-#define SMB_ACL_NEXT_ENTRY 1
-
-#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
-#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
-
-#elif defined(HAVE_AIX_ACLS)
-
-/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
-
-#include <acl.h>
-
-typedef uint *SMB_ACL_PERMSET_T;
-
-struct acl_entry_link{
- struct acl_entry_link *prevp;
- struct new_acl_entry *entryp;
- struct acl_entry_link *nextp;
- int count;
-};
-
-struct new_acl_entry{
- unsigned short ace_len;
- unsigned short ace_type;
- unsigned int ace_access;
- struct ace_id ace_id[1];
-};
-
-#define SMB_ACL_ENTRY_T struct new_acl_entry*
-#define SMB_ACL_T struct acl_entry_link*
-
-#define SMB_ACL_TAG_T unsigned short
-#define SMB_ACL_TYPE_T int
-#define SMB_ACL_PERM_T uint
-#define SMB_ACL_READ S_IRUSR
-#define SMB_ACL_WRITE S_IWUSR
-#define SMB_ACL_EXECUTE S_IXUSR
-
-/* Types of ACLs. */
-#define SMB_ACL_USER ACEID_USER
-#define SMB_ACL_USER_OBJ 3
-#define SMB_ACL_GROUP ACEID_GROUP
-#define SMB_ACL_GROUP_OBJ 4
-#define SMB_ACL_OTHER 5
-#define SMB_ACL_MASK 6
-
-
-#define SMB_ACL_FIRST_ENTRY 1
-#define SMB_ACL_NEXT_ENTRY 2
-
-#define SMB_ACL_TYPE_ACCESS 0
-#define SMB_ACL_TYPE_DEFAULT 1
-
-#else /* No ACLs. */
-
-/* No ACLS - fake it. */
-#define SMB_ACL_TAG_T int
-#define SMB_ACL_TYPE_T int
-#define SMB_ACL_PERMSET_T mode_t
-#define SMB_ACL_PERM_T mode_t
-#define SMB_ACL_READ S_IRUSR
-#define SMB_ACL_WRITE S_IWUSR
-#define SMB_ACL_EXECUTE S_IXUSR
-
-/* Types of ACLs. */
-#define SMB_ACL_USER 0
-#define SMB_ACL_USER_OBJ 1
-#define SMB_ACL_GROUP 2
-#define SMB_ACL_GROUP_OBJ 3
-#define SMB_ACL_OTHER 4
-#define SMB_ACL_MASK 5
-
-typedef struct SMB_ACL_T_ {
- int dummy;
+ struct smb_acl_entry acl[1];
} *SMB_ACL_T;
-typedef struct SMB_ACL_ENTRY_T_ {
- int dummy;
-} *SMB_ACL_ENTRY_T;
+typedef struct smb_acl_entry *SMB_ACL_ENTRY_T;
#define SMB_ACL_FIRST_ENTRY 0
#define SMB_ACL_NEXT_ENTRY 1
@@ -271,5 +63,4 @@ typedef struct SMB_ACL_ENTRY_T_ {
#define SMB_ACL_TYPE_ACCESS 0
#define SMB_ACL_TYPE_DEFAULT 1
-#endif /* No ACLs. */
#endif /* _SMB_ACLS_H */
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index 554dbbc0878..add7dcd31c2 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -83,30 +83,32 @@
#define SMB_ASSERT_ARRAY(a,n) SMB_ASSERT((sizeof(a)/sizeof((a)[0])) >= (n))
/* these are useful macros for checking validity of handles */
-#define OPEN_FSP(fsp) ((fsp) && !(fsp)->is_directory)
-#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
+ * (do not add it to the macro as that causes nested extern declaration warnings)
* 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));\
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
} while(0)
-#define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid)
+#define FNUM_OK(fsp,c) ((fsp) && !(fsp)->is_directory && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid)
/* you must add the following extern declaration to files using this macro
+ * (do not add it to the macro as that causes nested extern declaration warnings)
* 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)->fh->fd == -1) \
- return(ERROR_DOS(ERRDOS,ERRbadaccess));\
+ if (!(fsp) || !(conn)) \
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
+ else if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) \
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE); \
+ else if ((fsp)->is_directory) \
+ return ERROR_NT(NT_STATUS_INVALID_DEVICE_REQUEST); \
+ else if ((fsp)->fh->fd == -1) \
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED); \
(fsp)->num_smb_operations++;\
} while(0)
@@ -122,7 +124,7 @@
/* the service number for the [globals] defaults */
#define GLOBAL_SECTION_SNUM (-1)
/* translates a connection number into a service number */
-#define SNUM(conn) ((conn)?(conn)->service:GLOBAL_SECTION_SNUM)
+#define SNUM(conn) ((conn)?(conn)->params->service:GLOBAL_SECTION_SNUM)
/* access various service details */
@@ -133,10 +135,10 @@
#define GUEST_OK(snum) (VALID_SNUM(snum) && lp_guest_ok(snum))
#define GUEST_ONLY(snum) (VALID_SNUM(snum) && lp_guest_only(snum))
#define CAN_SETDIR(snum) (!lp_no_set_dir(snum))
-#define CAN_PRINT(conn) ((conn) && lp_print_ok((conn)->service))
-#define MAP_HIDDEN(conn) ((conn) && lp_map_hidden((conn)->service))
-#define MAP_SYSTEM(conn) ((conn) && lp_map_system((conn)->service))
-#define MAP_ARCHIVE(conn) ((conn) && lp_map_archive((conn)->service))
+#define CAN_PRINT(conn) ((conn) && lp_print_ok(SNUM(conn)))
+#define MAP_HIDDEN(conn) ((conn) && lp_map_hidden(SNUM(conn)))
+#define MAP_SYSTEM(conn) ((conn) && lp_map_system(SNUM(conn)))
+#define MAP_ARCHIVE(conn) ((conn) && lp_map_archive(SNUM(conn)))
#define IS_HIDDEN_PATH(conn,path) ((conn) && is_in_path((path),(conn)->hide_list,(conn)->case_sensitive))
#define IS_VETO_PATH(conn,path) ((conn) && is_in_path((path),(conn)->veto_list,(conn)->case_sensitive))
#define IS_VETO_OPLOCK_PATH(conn,path) ((conn) && is_in_path((path),(conn)->veto_oplock_list,(conn)->case_sensitive))
@@ -182,7 +184,6 @@
#define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__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__)
@@ -275,6 +276,7 @@ copy an IP address from one buffer to another
*****************************************************************************/
#define SMB_MALLOC_ARRAY(type,count) (type *)malloc_array(sizeof(type),(count))
+#define SMB_MEMALIGN_ARRAY(type,align,count) (type *)memalign_array(sizeof(type),align,(count))
#define SMB_REALLOC(p,s) Realloc((p),(s),True) /* Always frees p on error or s == 0 */
#define SMB_REALLOC_KEEP_OLD_ON_ERROR(p,s) Realloc((p),(s),False) /* Never frees p on error or s == 0 */
#define SMB_REALLOC_ARRAY(p,type,count) (type *)realloc_array((p),sizeof(type),(count),True) /* Always frees p on error or s == 0 */
@@ -284,7 +286,7 @@ copy an IP address from one buffer to another
#define SMB_XMALLOC_ARRAY(type,count) (type *)smb_xmalloc_array(sizeof(type),(count))
/* limiting size of ipc replies */
-#define SMB_REALLOC_LIMIT(ptr,size) SMB_REALLOC(ptr,MAX((size),4*1024))
+#define SMB_REALLOC_LIMIT(ptr,size) (char *)SMB_REALLOC(ptr,MAX((size),4*1024))
/* The new talloc is paranoid malloc checker safe. */
@@ -377,6 +379,14 @@ do { \
} while (0)
#define ADD_TO_LARGE_ARRAY(mem_ctx, type, elem, array, num, size) \
- add_to_large_array((mem_ctx), sizeof(type), &(elem), (void **)(array), (num), (size));
+ add_to_large_array((mem_ctx), sizeof(type), &(elem), (void *)(array), (num), (size));
+
+#ifndef ISDOT
+#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0')
+#endif /* ISDOT */
+
+#ifndef ISDOTDOT
+#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0')
+#endif /* ISDOTDOT */
#endif /* _SMB_MACROS_H */
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index ae54e66b369..390b8f681a4 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -158,8 +158,12 @@ struct smbldap_state {
time_t last_ping;
/* retrive-once info */
const char *uri;
+
+ /* credentials */
+ BOOL anonymous;
char *bind_dn;
char *bind_secret;
+
BOOL paged_results;
unsigned int num_failures;
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index b8a9a49be1a..fa7c6e4a5ae 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -4,7 +4,8 @@
Unix SMB/CIFS implementation.
store smbd profiling information in shared memory
Copyright (C) Andrew Tridgell 1999
-
+ Copyright (C) James Peach 2006
+
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
@@ -26,102 +27,719 @@
#define PROF_SHMEM_KEY ((key_t)0x07021999)
#define PROF_SHM_MAGIC 0x6349985
-#define PROF_SHM_VERSION 10
+#define PROF_SHM_VERSION 11
/* time values in the following structure are in microseconds */
+#define __profile_stats_value(which, domain) domain[which]
+
+enum profile_stats_values
+{
+ PR_VALUE_SMBD_IDLE = 0,
+#define smbd_idle_count __profile_stats_value(PR_VALUE_SMBD_IDLE, count)
+#define smbd_idle_time __profile_stats_value(PR_VALUE_SMBD_IDLE, time)
+
+/* system call counters */
+ PR_VALUE_SYSCALL_OPENDIR,
+#define syscall_opendir_count __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, count)
+#define syscall_opendir_time __profile_stats_value(PR_VALUE_SYSCALL_OPENDIR, time)
+
+ PR_VALUE_SYSCALL_READDIR,
+#define syscall_readdir_count __profile_stats_value(PR_VALUE_SYSCALL_READDIR, count)
+#define syscall_readdir_time __profile_stats_value(PR_VALUE_SYSCALL_READDIR, time)
+
+ PR_VALUE_SYSCALL_SEEKDIR,
+#define syscall_seekdir_count __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, count)
+#define syscall_seekdir_time __profile_stats_value(PR_VALUE_SYSCALL_SEEKDIR, time)
+
+ PR_VALUE_SYSCALL_TELLDIR,
+#define syscall_telldir_count __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, count)
+#define syscall_telldir_time __profile_stats_value(PR_VALUE_SYSCALL_TELLDIR, time)
+
+ PR_VALUE_SYSCALL_REWINDDIR,
+#define syscall_rewinddir_count __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, count)
+#define syscall_rewinddir_time __profile_stats_value(PR_VALUE_SYSCALL_REWINDDIR, time)
+
+ PR_VALUE_SYSCALL_MKDIR,
+#define syscall_mkdir_count __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, count)
+#define syscall_mkdir_time __profile_stats_value(PR_VALUE_SYSCALL_MKDIR, time)
+
+ PR_VALUE_SYSCALL_RMDIR,
+#define syscall_rmdir_count __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, count)
+#define syscall_rmdir_time __profile_stats_value(PR_VALUE_SYSCALL_RMDIR, time)
+
+ PR_VALUE_SYSCALL_CLOSEDIR,
+#define syscall_closedir_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, count)
+#define syscall_closedir_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSEDIR, time)
+
+ PR_VALUE_SYSCALL_OPEN,
+#define syscall_open_count __profile_stats_value(PR_VALUE_SYSCALL_OPEN, count)
+#define syscall_open_time __profile_stats_value(PR_VALUE_SYSCALL_OPEN, time)
+
+ PR_VALUE_SYSCALL_CLOSE,
+#define syscall_close_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, count)
+#define syscall_close_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, time)
+
+ PR_VALUE_SYSCALL_READ,
+#define syscall_read_count __profile_stats_value(PR_VALUE_SYSCALL_READ, count)
+#define syscall_read_time __profile_stats_value(PR_VALUE_SYSCALL_READ, time)
+
+ PR_VALUE_SYSCALL_PREAD,
+#define syscall_pread_count __profile_stats_value(PR_VALUE_SYSCALL_PREAD, count)
+#define syscall_pread_time __profile_stats_value(PR_VALUE_SYSCALL_PREAD, time)
+
+ PR_VALUE_SYSCALL_WRITE,
+#define syscall_write_count __profile_stats_value(PR_VALUE_SYSCALL_WRITE, count)
+#define syscall_write_time __profile_stats_value(PR_VALUE_SYSCALL_WRITE, time)
+
+ PR_VALUE_SYSCALL_PWRITE,
+#define syscall_pwrite_count __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, count)
+#define syscall_pwrite_time __profile_stats_value(PR_VALUE_SYSCALL_PWRITE, time)
+
+ PR_VALUE_SYSCALL_LSEEK,
+#define syscall_lseek_count __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, count)
+#define syscall_lseek_time __profile_stats_value(PR_VALUE_SYSCALL_LSEEK, time)
+
+ PR_VALUE_SYSCALL_SENDFILE,
+#define syscall_sendfile_count __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, count)
+#define syscall_sendfile_time __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, time)
+
+ PR_VALUE_SYSCALL_RENAME,
+#define syscall_rename_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME, count)
+#define syscall_rename_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME, time)
+
+ PR_VALUE_SYSCALL_FSYNC,
+#define syscall_fsync_count __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, count)
+#define syscall_fsync_time __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, time)
+
+ PR_VALUE_SYSCALL_STAT,
+#define syscall_stat_count __profile_stats_value(PR_VALUE_SYSCALL_STAT, count)
+#define syscall_stat_time __profile_stats_value(PR_VALUE_SYSCALL_STAT, time)
+
+ PR_VALUE_SYSCALL_FSTAT,
+#define syscall_fstat_count __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, count)
+#define syscall_fstat_time __profile_stats_value(PR_VALUE_SYSCALL_FSTAT, time)
+
+ PR_VALUE_SYSCALL_LSTAT,
+#define syscall_lstat_count __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, count)
+#define syscall_lstat_time __profile_stats_value(PR_VALUE_SYSCALL_LSTAT, time)
+
+ PR_VALUE_SYSCALL_UNLINK,
+#define syscall_unlink_count __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, count)
+#define syscall_unlink_time __profile_stats_value(PR_VALUE_SYSCALL_UNLINK, time)
+
+ PR_VALUE_SYSCALL_CHMOD,
+#define syscall_chmod_count __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, count)
+#define syscall_chmod_time __profile_stats_value(PR_VALUE_SYSCALL_CHMOD, time)
+
+ PR_VALUE_SYSCALL_FCHMOD,
+#define syscall_fchmod_count __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, count)
+#define syscall_fchmod_time __profile_stats_value(PR_VALUE_SYSCALL_FCHMOD, time)
+
+ PR_VALUE_SYSCALL_CHOWN,
+#define syscall_chown_count __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, count)
+#define syscall_chown_time __profile_stats_value(PR_VALUE_SYSCALL_CHOWN, time)
+
+ PR_VALUE_SYSCALL_FCHOWN,
+#define syscall_fchown_count __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, count)
+#define syscall_fchown_time __profile_stats_value(PR_VALUE_SYSCALL_FCHOWN, time)
+
+ PR_VALUE_SYSCALL_CHDIR,
+#define syscall_chdir_count __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, count)
+#define syscall_chdir_time __profile_stats_value(PR_VALUE_SYSCALL_CHDIR, time)
+
+ PR_VALUE_SYSCALL_GETWD,
+#define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count)
+#define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time)
+
+ PR_VALUE_SYSCALL_UTIME,
+#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count)
+#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time)
+
+ PR_VALUE_SYSCALL_FTRUNCATE,
+#define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count)
+#define syscall_ftruncate_time __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, time)
+
+ PR_VALUE_SYSCALL_FCNTL_LOCK,
+#define syscall_fcntl_lock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, count)
+#define syscall_fcntl_lock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_LOCK, time)
+
+ PR_VALUE_SYSCALL_KERNEL_FLOCK,
+#define syscall_kernel_flock_count __profile_stats_value(PR_VALUE_SYSCALL_KERNEL_FLOCK, count)
+#define syscall_kernel_flock_time __profile_stats_value(PR_VALUE_SYSCALL_KERNEL_FLOCK, time)
+
+ PR_VALUE_SYSCALL_LINUX_SETLEASE,
+#define syscall_linux_setlease_count __profile_stats_value(PR_VALUE_SYSCALL_LINUX_SETLEASE, count)
+#define syscall_linux_setlease_time __profile_stats_value(PR_VALUE_SYSCALL_LINUX_SETLEASE, time)
+
+ PR_VALUE_SYSCALL_FCNTL_GETLOCK,
+#define syscall_fcntl_getlock_count __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, count)
+#define syscall_fcntl_getlock_time __profile_stats_value(PR_VALUE_SYSCALL_FCNTL_GETLOCK, time)
+
+ PR_VALUE_SYSCALL_READLINK,
+#define syscall_readlink_count __profile_stats_value(PR_VALUE_SYSCALL_READLINK, count)
+#define syscall_readlink_time __profile_stats_value(PR_VALUE_SYSCALL_READLINK, time)
+
+ PR_VALUE_SYSCALL_SYMLINK,
+#define syscall_symlink_count __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, count)
+#define syscall_symlink_time __profile_stats_value(PR_VALUE_SYSCALL_SYMLINK, time)
+
+ PR_VALUE_SYSCALL_LINK,
+#define syscall_link_count __profile_stats_value(PR_VALUE_SYSCALL_LINK, count)
+#define syscall_link_time __profile_stats_value(PR_VALUE_SYSCALL_LINK, time)
+
+ PR_VALUE_SYSCALL_MKNOD,
+#define syscall_mknod_count __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, count)
+#define syscall_mknod_time __profile_stats_value(PR_VALUE_SYSCALL_MKNOD, time)
+
+ PR_VALUE_SYSCALL_REALPATH,
+#define syscall_realpath_count __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, count)
+#define syscall_realpath_time __profile_stats_value(PR_VALUE_SYSCALL_REALPATH, time)
+
+ PR_VALUE_SYSCALL_GET_QUOTA,
+#define syscall_get_quota_count __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, count)
+#define syscall_get_quota_time __profile_stats_value(PR_VALUE_SYSCALL_GET_QUOTA, time)
+
+ PR_VALUE_SYSCALL_SET_QUOTA,
+#define syscall_set_quota_count __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, count)
+#define syscall_set_quota_time __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, time)
+
+/* counters for individual SMB types */
+ PR_VALUE_SMBMKDIR,
+#define SMBmkdir_count __profile_stats_value(PR_VALUE_SMBMKDIR, count)
+#define SMBmkdir_time __profile_stats_value(PR_VALUE_SMBMKDIR, time)
+
+ PR_VALUE_SMBRMDIR,
+#define SMBrmdir_count __profile_stats_value(PR_VALUE_SMBRMDIR, count)
+#define SMBrmdir_time __profile_stats_value(PR_VALUE_SMBRMDIR, time)
+
+ PR_VALUE_SMBOPEN,
+#define SMBopen_count __profile_stats_value(PR_VALUE_SMBOPEN, count)
+#define SMBopen_time __profile_stats_value(PR_VALUE_SMBOPEN, time)
+
+ PR_VALUE_SMBCREATE,
+#define SMBcreate_count __profile_stats_value(PR_VALUE_SMBCREATE, count)
+#define SMBcreate_time __profile_stats_value(PR_VALUE_SMBCREATE, time)
+
+ PR_VALUE_SMBCLOSE,
+#define SMBclose_count __profile_stats_value(PR_VALUE_SMBCLOSE, count)
+#define SMBclose_time __profile_stats_value(PR_VALUE_SMBCLOSE, time)
+
+ PR_VALUE_SMBFLUSH,
+#define SMBflush_count __profile_stats_value(PR_VALUE_SMBFLUSH, count)
+#define SMBflush_time __profile_stats_value(PR_VALUE_SMBFLUSH, time)
+
+ PR_VALUE_SMBUNLINK,
+#define SMBunlink_count __profile_stats_value(PR_VALUE_SMBUNLINK, count)
+#define SMBunlink_time __profile_stats_value(PR_VALUE_SMBUNLINK, time)
+
+ PR_VALUE_SMBMV,
+#define SMBmv_count __profile_stats_value(PR_VALUE_SMBMV, count)
+#define SMBmv_time __profile_stats_value(PR_VALUE_SMBMV, time)
+
+ PR_VALUE_SMBGETATR,
+#define SMBgetatr_count __profile_stats_value(PR_VALUE_SMBGETATR, count)
+#define SMBgetatr_time __profile_stats_value(PR_VALUE_SMBGETATR, time)
+
+ PR_VALUE_SMBSETATR,
+#define SMBsetatr_count __profile_stats_value(PR_VALUE_SMBSETATR, count)
+#define SMBsetatr_time __profile_stats_value(PR_VALUE_SMBSETATR, time)
+
+ PR_VALUE_SMBREAD,
+#define SMBread_count __profile_stats_value(PR_VALUE_SMBREAD, count)
+#define SMBread_time __profile_stats_value(PR_VALUE_SMBREAD, time)
+
+ PR_VALUE_SMBWRITE,
+#define SMBwrite_count __profile_stats_value(PR_VALUE_SMBWRITE, count)
+#define SMBwrite_time __profile_stats_value(PR_VALUE_SMBWRITE, time)
+
+ PR_VALUE_SMBLOCK,
+#define SMBlock_count __profile_stats_value(PR_VALUE_SMBLOCK, count)
+#define SMBlock_time __profile_stats_value(PR_VALUE_SMBLOCK, time)
+
+ PR_VALUE_SMBUNLOCK,
+#define SMBunlock_count __profile_stats_value(PR_VALUE_SMBUNLOCK, count)
+#define SMBunlock_time __profile_stats_value(PR_VALUE_SMBUNLOCK, time)
+
+ PR_VALUE_SMBCTEMP,
+#define SMBctemp_count __profile_stats_value(PR_VALUE_SMBCTEMP, count)
+#define SMBctemp_time __profile_stats_value(PR_VALUE_SMBCTEMP, time)
+
+ /* SMBmknew stats are currently combined with SMBcreate */
+ PR_VALUE_SMBMKNEW,
+#define SMBmknew_count __profile_stats_value(PR_VALUE_SMBMKNEW, count)
+#define SMBmknew_time __profile_stats_value(PR_VALUE_SMBMKNEW, time)
+
+ PR_VALUE_SMBCHECKPATH,
+#define SMBcheckpath_count __profile_stats_value(PR_VALUE_SMBCHECKPATH, count)
+#define SMBcheckpath_time __profile_stats_value(PR_VALUE_SMBCHECKPATH, time)
+
+ PR_VALUE_SMBEXIT,
+#define SMBexit_count __profile_stats_value(PR_VALUE_SMBEXIT, count)
+#define SMBexit_time __profile_stats_value(PR_VALUE_SMBEXIT, time)
+
+ PR_VALUE_SMBLSEEK,
+#define SMBlseek_count __profile_stats_value(PR_VALUE_SMBLSEEK, count)
+#define SMBlseek_time __profile_stats_value(PR_VALUE_SMBLSEEK, time)
+
+ PR_VALUE_SMBLOCKREAD,
+#define SMBlockread_count __profile_stats_value(PR_VALUE_SMBLOCKREAD, count)
+#define SMBlockread_time __profile_stats_value(PR_VALUE_SMBLOCKREAD, time)
+
+ PR_VALUE_SMBWRITEUNLOCK,
+#define SMBwriteunlock_count __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, count)
+#define SMBwriteunlock_time __profile_stats_value(PR_VALUE_SMBWRITEUNLOCK, time)
+
+ PR_VALUE_SMBREADBRAW,
+#define SMBreadbraw_count __profile_stats_value(PR_VALUE_SMBREADBRAW, count)
+#define SMBreadbraw_time __profile_stats_value(PR_VALUE_SMBREADBRAW, time)
+
+ PR_VALUE_SMBREADBMPX,
+#define SMBreadBmpx_count __profile_stats_value(PR_VALUE_SMBREADBMPX, count)
+#define SMBreadBmpx_time __profile_stats_value(PR_VALUE_SMBREADBMPX, time)
+
+ PR_VALUE_SMBREADBS,
+#define SMBreadBs_count __profile_stats_value(PR_VALUE_SMBREADBS, count)
+#define SMBreadBs_time __profile_stats_value(PR_VALUE_SMBREADBS, time)
+
+ PR_VALUE_SMBWRITEBRAW,
+#define SMBwritebraw_count __profile_stats_value(PR_VALUE_SMBWRITEBRAW, count)
+#define SMBwritebraw_time __profile_stats_value(PR_VALUE_SMBWRITEBRAW, time)
+
+ PR_VALUE_SMBWRITEBMPX,
+#define SMBwriteBmpx_count __profile_stats_value(PR_VALUE_SMBWRITEBMPX, count)
+#define SMBwriteBmpx_time __profile_stats_value(PR_VALUE_SMBWRITEBMPX, time)
+
+ PR_VALUE_SMBWRITEBS,
+#define SMBwriteBs_count __profile_stats_value(PR_VALUE_SMBWRITEBS, count)
+#define SMBwriteBs_time __profile_stats_value(PR_VALUE_SMBWRITEBS, time)
+
+ PR_VALUE_SMBWRITEC,
+#define SMBwritec_count __profile_stats_value(PR_VALUE_SMBWRITEC, count)
+#define SMBwritec_time __profile_stats_value(PR_VALUE_SMBWRITEC, time)
+
+ PR_VALUE_SMBSETATTRE,
+#define SMBsetattrE_count __profile_stats_value(PR_VALUE_SMBSETATTRE, count)
+#define SMBsetattrE_time __profile_stats_value(PR_VALUE_SMBSETATTRE, time)
+
+ PR_VALUE_SMBGETATTRE,
+#define SMBgetattrE_count __profile_stats_value(PR_VALUE_SMBGETATTRE, count)
+#define SMBgetattrE_time __profile_stats_value(PR_VALUE_SMBGETATTRE, time)
+
+ PR_VALUE_SMBLOCKINGX,
+#define SMBlockingX_count __profile_stats_value(PR_VALUE_SMBLOCKINGX, count)
+#define SMBlockingX_time __profile_stats_value(PR_VALUE_SMBLOCKINGX, time)
+
+ PR_VALUE_SMBTRANS,
+#define SMBtrans_count __profile_stats_value(PR_VALUE_SMBTRANS, count)
+#define SMBtrans_time __profile_stats_value(PR_VALUE_SMBTRANS, time)
+
+ PR_VALUE_SMBTRANSS,
+#define SMBtranss_count __profile_stats_value(PR_VALUE_SMBTRANSS, count)
+#define SMBtranss_time __profile_stats_value(PR_VALUE_SMBTRANSS, time)
+
+ PR_VALUE_SMBIOCTL,
+#define SMBioctl_count __profile_stats_value(PR_VALUE_SMBIOCTL, count)
+#define SMBioctl_time __profile_stats_value(PR_VALUE_SMBIOCTL, time)
+
+ PR_VALUE_SMBIOCTLS,
+#define SMBioctls_count __profile_stats_value(PR_VALUE_SMBIOCTLS, count)
+#define SMBioctls_time __profile_stats_value(PR_VALUE_SMBIOCTLS, time)
+
+ PR_VALUE_SMBCOPY,
+#define SMBcopy_count __profile_stats_value(PR_VALUE_SMBCOPY, count)
+#define SMBcopy_time __profile_stats_value(PR_VALUE_SMBCOPY, time)
+
+ PR_VALUE_SMBMOVE,
+#define SMBmove_count __profile_stats_value(PR_VALUE_SMBMOVE, count)
+#define SMBmove_time __profile_stats_value(PR_VALUE_SMBMOVE, time)
+
+ PR_VALUE_SMBECHO,
+#define SMBecho_count __profile_stats_value(PR_VALUE_SMBECHO, count)
+#define SMBecho_time __profile_stats_value(PR_VALUE_SMBECHO, time)
+
+ PR_VALUE_SMBWRITECLOSE,
+#define SMBwriteclose_count __profile_stats_value(PR_VALUE_SMBWRITECLOSE, count)
+#define SMBwriteclose_time __profile_stats_value(PR_VALUE_SMBWRITECLOSE, time)
+
+ PR_VALUE_SMBOPENX,
+#define SMBopenX_count __profile_stats_value(PR_VALUE_SMBOPENX, count)
+#define SMBopenX_time __profile_stats_value(PR_VALUE_SMBOPENX, time)
+
+ PR_VALUE_SMBREADX,
+#define SMBreadX_count __profile_stats_value(PR_VALUE_SMBREADX, count)
+#define SMBreadX_time __profile_stats_value(PR_VALUE_SMBREADX, time)
+
+ PR_VALUE_SMBWRITEX,
+#define SMBwriteX_count __profile_stats_value(PR_VALUE_SMBWRITEX, count)
+#define SMBwriteX_time __profile_stats_value(PR_VALUE_SMBWRITEX, time)
+
+ PR_VALUE_SMBTRANS2,
+#define SMBtrans2_count __profile_stats_value(PR_VALUE_SMBTRANS2, count)
+#define SMBtrans2_time __profile_stats_value(PR_VALUE_SMBTRANS2, time)
+
+ PR_VALUE_SMBTRANSS2,
+#define SMBtranss2_count __profile_stats_value(PR_VALUE_SMBTRANSS2, count)
+#define SMBtranss2_time __profile_stats_value(PR_VALUE_SMBTRANSS2, time)
+
+ PR_VALUE_SMBFINDCLOSE,
+#define SMBfindclose_count __profile_stats_value(PR_VALUE_SMBFINDCLOSE, count)
+#define SMBfindclose_time __profile_stats_value(PR_VALUE_SMBFINDCLOSE, time)
+
+ PR_VALUE_SMBFINDNCLOSE,
+#define SMBfindnclose_count __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, count)
+#define SMBfindnclose_time __profile_stats_value(PR_VALUE_SMBFINDNCLOSE, time)
+
+ PR_VALUE_SMBTCON,
+#define SMBtcon_count __profile_stats_value(PR_VALUE_SMBTCON, count)
+#define SMBtcon_time __profile_stats_value(PR_VALUE_SMBTCON, time)
+
+ PR_VALUE_SMBTDIS,
+#define SMBtdis_count __profile_stats_value(PR_VALUE_SMBTDIS, count)
+#define SMBtdis_time __profile_stats_value(PR_VALUE_SMBTDIS, time)
+
+ PR_VALUE_SMBNEGPROT,
+#define SMBnegprot_count __profile_stats_value(PR_VALUE_SMBNEGPROT, count)
+#define SMBnegprot_time __profile_stats_value(PR_VALUE_SMBNEGPROT, time)
+
+ PR_VALUE_SMBSESSSETUPX,
+#define SMBsesssetupX_count __profile_stats_value(PR_VALUE_SMBSESSSETUPX, count)
+#define SMBsesssetupX_time __profile_stats_value(PR_VALUE_SMBSESSSETUPX, time)
+
+ PR_VALUE_SMBULOGOFFX,
+#define SMBulogoffX_count __profile_stats_value(PR_VALUE_SMBULOGOFFX, count)
+#define SMBulogoffX_time __profile_stats_value(PR_VALUE_SMBULOGOFFX, time)
+
+ PR_VALUE_SMBTCONX,
+#define SMBtconX_count __profile_stats_value(PR_VALUE_SMBTCONX, count)
+#define SMBtconX_time __profile_stats_value(PR_VALUE_SMBTCONX, time)
+
+ PR_VALUE_SMBDSKATTR,
+#define SMBdskattr_count __profile_stats_value(PR_VALUE_SMBDSKATTR, count)
+#define SMBdskattr_time __profile_stats_value(PR_VALUE_SMBDSKATTR, time)
+
+ PR_VALUE_SMBSEARCH,
+#define SMBsearch_count __profile_stats_value(PR_VALUE_SMBSEARCH, count)
+#define SMBsearch_time __profile_stats_value(PR_VALUE_SMBSEARCH, time)
+
+ /* SBMffirst stats combined with SMBsearch */
+ PR_VALUE_SMBFFIRST,
+#define SMBffirst_count __profile_stats_value(PR_VALUE_SMBFFIRST, count)
+#define SMBffirst_time __profile_stats_value(PR_VALUE_SMBFFIRST, time)
+
+ /* SBMfunique stats combined with SMBsearch */
+ PR_VALUE_SMBFUNIQUE,
+#define SMBfunique_count __profile_stats_value(PR_VALUE_SMBFUNIQUE, count)
+#define SMBfunique_time __profile_stats_value(PR_VALUE_SMBFUNIQUE, time)
+
+ PR_VALUE_SMBFCLOSE,
+#define SMBfclose_count __profile_stats_value(PR_VALUE_SMBFCLOSE, count)
+#define SMBfclose_time __profile_stats_value(PR_VALUE_SMBFCLOSE, time)
+
+ PR_VALUE_SMBNTTRANS,
+#define SMBnttrans_count __profile_stats_value(PR_VALUE_SMBNTTRANS, count)
+#define SMBnttrans_time __profile_stats_value(PR_VALUE_SMBNTTRANS, time)
+
+ PR_VALUE_SMBNTTRANSS,
+#define SMBnttranss_count __profile_stats_value(PR_VALUE_SMBNTTRANSS, count)
+#define SMBnttranss_time __profile_stats_value(PR_VALUE_SMBNTTRANSS, time)
+
+ PR_VALUE_SMBNTCREATEX,
+#define SMBntcreateX_count __profile_stats_value(PR_VALUE_SMBNTCREATEX, count)
+#define SMBntcreateX_time __profile_stats_value(PR_VALUE_SMBNTCREATEX, time)
+
+ PR_VALUE_SMBNTCANCEL,
+#define SMBntcancel_count __profile_stats_value(PR_VALUE_SMBNTCANCEL, count)
+#define SMBntcancel_time __profile_stats_value(PR_VALUE_SMBNTCANCEL, time)
+
+ PR_VALUE_SMBNTRENAME,
+#define SMBntrename_count __profile_stats_value(PR_VALUE_SMBNTRENAME, count)
+#define SMBntrename_time __profile_stats_value(PR_VALUE_SMBNTRENAME, time)
+
+ PR_VALUE_SMBSPLOPEN,
+#define SMBsplopen_count __profile_stats_value(PR_VALUE_SMBSPLOPEN, count)
+#define SMBsplopen_time __profile_stats_value(PR_VALUE_SMBSPLOPEN, time)
+
+ PR_VALUE_SMBSPLWR,
+#define SMBsplwr_count __profile_stats_value(PR_VALUE_SMBSPLWR, count)
+#define SMBsplwr_time __profile_stats_value(PR_VALUE_SMBSPLWR, time)
+
+ PR_VALUE_SMBSPLCLOSE,
+#define SMBsplclose_count __profile_stats_value(PR_VALUE_SMBSPLCLOSE, count)
+#define SMBsplclose_time __profile_stats_value(PR_VALUE_SMBSPLCLOSE, time)
+
+ PR_VALUE_SMBSPLRETQ,
+#define SMBsplretq_count __profile_stats_value(PR_VALUE_SMBSPLRETQ, count)
+#define SMBsplretq_time __profile_stats_value(PR_VALUE_SMBSPLRETQ, time)
+
+ PR_VALUE_SMBSENDS,
+#define SMBsends_count __profile_stats_value(PR_VALUE_SMBSENDS, count)
+#define SMBsends_time __profile_stats_value(PR_VALUE_SMBSENDS, time)
+
+ PR_VALUE_SMBSENDB,
+#define SMBsendb_count __profile_stats_value(PR_VALUE_SMBSENDB, count)
+#define SMBsendb_time __profile_stats_value(PR_VALUE_SMBSENDB, time)
+
+ PR_VALUE_SMBFWDNAME,
+#define SMBfwdname_count __profile_stats_value(PR_VALUE_SMBFWDNAME, count)
+#define SMBfwdname_time __profile_stats_value(PR_VALUE_SMBFWDNAME, time)
+
+ PR_VALUE_SMBCANCELF,
+#define SMBcancelf_count __profile_stats_value(PR_VALUE_SMBCANCELF, count)
+#define SMBcancelf_time __profile_stats_value(PR_VALUE_SMBCANCELF, time)
+
+ PR_VALUE_SMBGETMAC,
+#define SMBgetmac_count __profile_stats_value(PR_VALUE_SMBGETMAC, count)
+#define SMBgetmac_time __profile_stats_value(PR_VALUE_SMBGETMAC, time)
+
+ PR_VALUE_SMBSENDSTRT,
+#define SMBsendstrt_count __profile_stats_value(PR_VALUE_SMBSENDSTRT, count)
+#define SMBsendstrt_time __profile_stats_value(PR_VALUE_SMBSENDSTRT, time)
+
+ PR_VALUE_SMBSENDEND,
+#define SMBsendend_count __profile_stats_value(PR_VALUE_SMBSENDEND, count)
+#define SMBsendend_time __profile_stats_value(PR_VALUE_SMBSENDEND, time)
+
+ PR_VALUE_SMBSENDTXT,
+#define SMBsendtxt_count __profile_stats_value(PR_VALUE_SMBSENDTXT, count)
+#define SMBsendtxt_time __profile_stats_value(PR_VALUE_SMBSENDTXT, time)
+
+ PR_VALUE_SMBINVALID,
+#define SMBinvalid_count __profile_stats_value(PR_VALUE_SMBINVALID, count)
+#define SMBinvalid_time __profile_stats_value(PR_VALUE_SMBINVALID, time)
+
+/* Pathworks setdir command */
+ PR_VALUE_PATHWORKS_SETDIR,
+#define pathworks_setdir_count __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, count)
+#define pathworks_setdir_time __profile_stats_value(PR_VALUE_PATHWORKS_SETDIR, time)
+
+/* These are the TRANS2 sub commands */
+ PR_VALUE_TRANS2_OPEN,
+#define Trans2_open_count __profile_stats_value(PR_VALUE_TRANS2_OPEN, count)
+#define Trans2_open_time __profile_stats_value(PR_VALUE_TRANS2_OPEN, time)
+
+ PR_VALUE_TRANS2_FINDFIRST,
+#define Trans2_findfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, count)
+#define Trans2_findfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDFIRST, time)
+
+ PR_VALUE_TRANS2_FINDNEXT,
+#define Trans2_findnext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, count)
+#define Trans2_findnext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNEXT, time)
+
+ PR_VALUE_TRANS2_QFSINFO,
+#define Trans2_qfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, count)
+#define Trans2_qfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFSINFO, time)
+
+ PR_VALUE_TRANS2_SETFSINFO,
+#define Trans2_setfsinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, count)
+#define Trans2_setfsinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFSINFO, time)
+
+ PR_VALUE_TRANS2_QPATHINFO,
+#define Trans2_qpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, count)
+#define Trans2_qpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_QPATHINFO, time)
+
+ PR_VALUE_TRANS2_SETPATHINFO,
+#define Trans2_setpathinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, count)
+#define Trans2_setpathinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETPATHINFO, time)
+
+ PR_VALUE_TRANS2_QFILEINFO,
+#define Trans2_qfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, count)
+#define Trans2_qfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_QFILEINFO, time)
+
+ PR_VALUE_TRANS2_SETFILEINFO,
+#define Trans2_setfileinfo_count __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, count)
+#define Trans2_setfileinfo_time __profile_stats_value(PR_VALUE_TRANS2_SETFILEINFO, time)
+
+ PR_VALUE_TRANS2_FSCTL,
+#define Trans2_fsctl_count __profile_stats_value(PR_VALUE_TRANS2_FSCTL, count)
+#define Trans2_fsctl_time __profile_stats_value(PR_VALUE_TRANS2_FSCTL, time)
+
+ PR_VALUE_TRANS2_IOCTL,
+#define Trans2_ioctl_count __profile_stats_value(PR_VALUE_TRANS2_IOCTL, count)
+#define Trans2_ioctl_time __profile_stats_value(PR_VALUE_TRANS2_IOCTL, time)
+
+ PR_VALUE_TRANS2_FINDNOTIFYFIRST,
+#define Trans2_findnotifyfirst_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, count)
+#define Trans2_findnotifyfirst_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYFIRST, time)
+
+ PR_VALUE_TRANS2_FINDNOTIFYNEXT,
+#define Trans2_findnotifynext_count __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, count)
+#define Trans2_findnotifynext_time __profile_stats_value(PR_VALUE_TRANS2_FINDNOTIFYNEXT, time)
+
+ PR_VALUE_TRANS2_MKDIR,
+#define Trans2_mkdir_count __profile_stats_value(PR_VALUE_TRANS2_MKDIR, count)
+#define Trans2_mkdir_time __profile_stats_value(PR_VALUE_TRANS2_MKDIR, time)
+
+ PR_VALUE_TRANS2_SESSION_SETUP,
+#define Trans2_session_setup_count __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, count)
+#define Trans2_session_setup_time __profile_stats_value(PR_VALUE_TRANS2_SESSION_SETUP, time)
+
+ PR_VALUE_TRANS2_GET_DFS_REFERRAL,
+#define Trans2_get_dfs_referral_count __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, count)
+#define Trans2_get_dfs_referral_time __profile_stats_value(PR_VALUE_TRANS2_GET_DFS_REFERRAL, time)
+
+ PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY,
+#define Trans2_report_dfs_inconsistancy_count __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, count)
+#define Trans2_report_dfs_inconsistancy_time __profile_stats_value(PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY, time)
+
+/* These are the NT transact sub commands. */
+ PR_VALUE_NT_TRANSACT_CREATE,
+#define NT_transact_create_count __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, count)
+#define NT_transact_create_time __profile_stats_value(PR_VALUE_NT_TRANSACT_CREATE, time)
+
+ PR_VALUE_NT_TRANSACT_IOCTL,
+#define NT_transact_ioctl_count __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, count)
+#define NT_transact_ioctl_time __profile_stats_value(PR_VALUE_NT_TRANSACT_IOCTL, time)
+
+ PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC,
+#define NT_transact_set_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, count)
+#define NT_transact_set_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC, time)
+
+ PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE,
+#define NT_transact_notify_change_count __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, count)
+#define NT_transact_notify_change_time __profile_stats_value(PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE, time)
+
+ PR_VALUE_NT_TRANSACT_RENAME,
+#define NT_transact_rename_count __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, count)
+#define NT_transact_rename_time __profile_stats_value(PR_VALUE_NT_TRANSACT_RENAME, time)
+
+ PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC,
+#define NT_transact_query_security_desc_count __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, count)
+#define NT_transact_query_security_desc_time __profile_stats_value(PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC, time)
+
+ PR_VALUE_NT_TRANSACT_GET_USER_QUOTA,
+#define NT_transact_get_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, count)
+#define NT_transact_get_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_GET_USER_QUOTA, time)
+
+ PR_VALUE_NT_TRANSACT_SET_USER_QUOTA,
+#define NT_transact_set_user_quota_count __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, count)
+#define NT_transact_set_user_quota_time __profile_stats_value(PR_VALUE_NT_TRANSACT_SET_USER_QUOTA, time)
+
+/* These are ACL manipulation calls */
+ PR_VALUE_GET_NT_ACL,
+#define get_nt_acl_count __profile_stats_value(PR_VALUE_GET_NT_ACL, count)
+#define get_nt_acl_time __profile_stats_value(PR_VALUE_GET_NT_ACL, time)
+
+ PR_VALUE_FGET_NT_ACL,
+#define fget_nt_acl_count __profile_stats_value(PR_VALUE_FGET_NT_ACL, count)
+#define fget_nt_acl_time __profile_stats_value(PR_VALUE_FGET_NT_ACL, time)
+
+ PR_VALUE_SET_NT_ACL,
+#define set_nt_acl_count __profile_stats_value(PR_VALUE_SET_NT_ACL, count)
+#define set_nt_acl_time __profile_stats_value(PR_VALUE_SET_NT_ACL, time)
+
+ PR_VALUE_FSET_NT_ACL,
+#define fset_nt_acl_count __profile_stats_value(PR_VALUE_FSET_NT_ACL, count)
+#define fset_nt_acl_time __profile_stats_value(PR_VALUE_FSET_NT_ACL, time)
+
+ PR_VALUE_CHMOD_ACL,
+#define chmod_acl_count __profile_stats_value(PR_VALUE_CHMOD_ACL, count)
+#define chmod_acl_time __profile_stats_value(PR_VALUE_CHMOD_ACL, time)
+
+ PR_VALUE_FCHMOD_ACL,
+#define fchmod_acl_count __profile_stats_value(PR_VALUE_FCHMOD_ACL, count)
+#define fchmod_acl_time __profile_stats_value(PR_VALUE_FCHMOD_ACL, time)
+
+/* These are nmbd stats */
+ PR_VALUE_NAME_RELEASE,
+#define name_release_count __profile_stats_value(PR_VALUE_NAME_RELEASE, count)
+#define name_release_time __profile_stats_value(PR_VALUE_NAME_RELEASE, time)
+
+ PR_VALUE_NAME_REFRESH,
+#define name_refresh_count __profile_stats_value(PR_VALUE_NAME_REFRESH, count)
+#define name_refresh_time __profile_stats_value(PR_VALUE_NAME_REFRESH, time)
+
+ PR_VALUE_NAME_REGISTRATION,
+#define name_registration_count __profile_stats_value(PR_VALUE_NAME_REGISTRATION, count)
+#define name_registration_time __profile_stats_value(PR_VALUE_NAME_REGISTRATION, time)
+
+ PR_VALUE_NODE_STATUS,
+#define node_status_count __profile_stats_value(PR_VALUE_NODE_STATUS, count)
+#define node_status_time __profile_stats_value(PR_VALUE_NODE_STATUS, time)
+
+ PR_VALUE_NAME_QUERY,
+#define name_query_count __profile_stats_value(PR_VALUE_NAME_QUERY, count)
+#define name_query_time __profile_stats_value(PR_VALUE_NAME_QUERY, time)
+
+ PR_VALUE_HOST_ANNOUNCE,
+#define host_announce_count __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, count)
+#define host_announce_time __profile_stats_value(PR_VALUE_HOST_ANNOUNCE, time)
+
+ PR_VALUE_WORKGROUP_ANNOUNCE,
+#define workgroup_announce_count __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, count)
+#define workgroup_announce_time __profile_stats_value(PR_VALUE_WORKGROUP_ANNOUNCE, time)
+
+ PR_VALUE_LOCAL_MASTER_ANNOUNCE,
+#define local_master_announce_count __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, count)
+#define local_master_announce_time __profile_stats_value(PR_VALUE_LOCAL_MASTER_ANNOUNCE, time)
+
+ PR_VALUE_MASTER_BROWSER_ANNOUNCE,
+#define master_browser_announce_count __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, count)
+#define master_browser_announce_time __profile_stats_value(PR_VALUE_MASTER_BROWSER_ANNOUNCE, time)
+
+ PR_VALUE_LM_HOST_ANNOUNCE,
+#define lm_host_announce_count __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, count)
+#define lm_host_announce_time __profile_stats_value(PR_VALUE_LM_HOST_ANNOUNCE, time)
+
+ PR_VALUE_GET_BACKUP_LIST,
+#define get_backup_list_count __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, count)
+#define get_backup_list_time __profile_stats_value(PR_VALUE_GET_BACKUP_LIST, time)
+
+ PR_VALUE_RESET_BROWSER,
+#define reset_browser_count __profile_stats_value(PR_VALUE_RESET_BROWSER, count)
+#define reset_browser_time __profile_stats_value(PR_VALUE_RESET_BROWSER, time)
+
+ PR_VALUE_ANNOUNCE_REQUEST,
+#define announce_request_count __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, count)
+#define announce_request_time __profile_stats_value(PR_VALUE_ANNOUNCE_REQUEST, time)
+
+ PR_VALUE_LM_ANNOUNCE_REQUEST,
+#define lm_announce_request_count __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, count)
+#define lm_announce_request_time __profile_stats_value(PR_VALUE_LM_ANNOUNCE_REQUEST, time)
+
+ PR_VALUE_DOMAIN_LOGON,
+#define domain_logon_count __profile_stats_value(PR_VALUE_DOMAIN_LOGON, count)
+#define domain_logon_time __profile_stats_value(PR_VALUE_DOMAIN_LOGON, time)
+
+ PR_VALUE_SYNC_BROWSE_LISTS,
+#define sync_browse_lists_count __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, count)
+#define sync_browse_lists_time __profile_stats_value(PR_VALUE_SYNC_BROWSE_LISTS, time)
+
+ PR_VALUE_RUN_ELECTIONS,
+#define run_elections_count __profile_stats_value(PR_VALUE_RUN_ELECTIONS, count)
+#define run_elections_time __profile_stats_value(PR_VALUE_RUN_ELECTIONS, time)
+
+ PR_VALUE_ELECTION,
+#define election_count __profile_stats_value(PR_VALUE_ELECTION, count)
+#define election_time __profile_stats_value(PR_VALUE_ELECTION, time)
+
+ /* This mist remain the last value. */
+ PR_VALUE_MAX
+}; /* enum profile_stats_values */
+
+const char * profile_value_name(enum profile_stats_values val);
+
struct profile_stats {
/* general counters */
unsigned smb_count; /* how many SMB packets we have processed */
unsigned uid_changes; /* how many times we change our effective uid */
-/* system call counters */
- unsigned syscall_opendir_count;
- unsigned syscall_opendir_time;
- unsigned syscall_readdir_count;
- unsigned syscall_readdir_time;
- unsigned syscall_seekdir_count;
- unsigned syscall_seekdir_time;
- unsigned syscall_telldir_count;
- unsigned syscall_telldir_time;
- unsigned syscall_rewinddir_count;
- unsigned syscall_rewinddir_time;
- unsigned syscall_mkdir_count;
- unsigned syscall_mkdir_time;
- unsigned syscall_rmdir_count;
- unsigned syscall_rmdir_time;
- unsigned syscall_closedir_count;
- unsigned syscall_closedir_time;
- unsigned syscall_open_count;
- unsigned syscall_open_time;
- unsigned syscall_close_count;
- unsigned syscall_close_time;
- unsigned syscall_read_count;
- unsigned syscall_read_time;
- unsigned syscall_read_bytes; /* bytes read with read syscall */
- unsigned syscall_pread_count;
- unsigned syscall_pread_time;
- unsigned syscall_pread_bytes; /* bytes read with pread syscall */
- unsigned syscall_write_count;
- unsigned syscall_write_time;
- unsigned syscall_write_bytes; /* bytes written with write syscall */
- unsigned syscall_pwrite_count;
- unsigned syscall_pwrite_time;
- unsigned syscall_pwrite_bytes; /* bytes written with pwrite syscall */
- unsigned syscall_lseek_count;
- unsigned syscall_lseek_time;
- unsigned syscall_sendfile_count;
- unsigned syscall_sendfile_time;
- unsigned syscall_sendfile_bytes; /* bytes read with sendfile syscall */
- unsigned syscall_rename_count;
- unsigned syscall_rename_time;
- unsigned syscall_fsync_count;
- unsigned syscall_fsync_time;
- unsigned syscall_stat_count;
- unsigned syscall_stat_time;
- unsigned syscall_fstat_count;
- unsigned syscall_fstat_time;
- unsigned syscall_lstat_count;
- unsigned syscall_lstat_time;
- unsigned syscall_unlink_count;
- unsigned syscall_unlink_time;
- unsigned syscall_chmod_count;
- unsigned syscall_chmod_time;
- unsigned syscall_fchmod_count;
- unsigned syscall_fchmod_time;
- unsigned syscall_chown_count;
- unsigned syscall_chown_time;
- unsigned syscall_fchown_count;
- unsigned syscall_fchown_time;
- unsigned syscall_chdir_count;
- unsigned syscall_chdir_time;
- unsigned syscall_getwd_count;
- unsigned syscall_getwd_time;
- unsigned syscall_utime_count;
- unsigned syscall_utime_time;
- unsigned syscall_ftruncate_count;
- unsigned syscall_ftruncate_time;
- unsigned syscall_fcntl_lock_count;
- unsigned syscall_fcntl_lock_time;
- unsigned syscall_fcntl_getlock_count;
- unsigned syscall_fcntl_getlock_time;
- unsigned syscall_readlink_count;
- unsigned syscall_readlink_time;
- unsigned syscall_symlink_count;
- unsigned syscall_symlink_time;
- unsigned syscall_link_count;
- unsigned syscall_link_time;
- unsigned syscall_mknod_count;
- unsigned syscall_mknod_time;
- unsigned syscall_realpath_count;
- unsigned syscall_realpath_time;
- unsigned syscall_get_quota_count;
- unsigned syscall_get_quota_time;
- unsigned syscall_set_quota_count;
- unsigned syscall_set_quota_time;
+
+/* system call and protocol operation counters and cumulative times */
+ unsigned count[PR_VALUE_MAX];
+ unsigned time[PR_VALUE_MAX];
+
+/* cumulative byte counts */
+ unsigned syscall_pread_bytes;
+ unsigned syscall_pwrite_bytes;
+ unsigned syscall_read_bytes;
+ unsigned syscall_write_bytes;
+ unsigned syscall_sendfile_bytes;
+
/* stat cache counters */
unsigned statcache_lookups;
unsigned statcache_misses;
unsigned statcache_hits;
+
/* write cache counters */
unsigned writecache_read_hits;
unsigned writecache_abutted_writes;
@@ -133,265 +751,6 @@ struct profile_stats {
unsigned writecache_num_perfect_writes;
unsigned writecache_num_write_caches;
unsigned writecache_allocated_write_caches;
-/* counters for individual SMB types */
- unsigned SMBmkdir_count; /* create directory */
- unsigned SMBmkdir_time;
- unsigned SMBrmdir_count; /* delete directory */
- unsigned SMBrmdir_time;
- unsigned SMBopen_count; /* open file */
- unsigned SMBopen_time;
- unsigned SMBcreate_count; /* create file */
- unsigned SMBcreate_time;
- unsigned SMBclose_count; /* close file */
- unsigned SMBclose_time;
- unsigned SMBflush_count; /* flush file */
- unsigned SMBflush_time;
- unsigned SMBunlink_count; /* delete file */
- unsigned SMBunlink_time;
- unsigned SMBmv_count; /* rename file */
- unsigned SMBmv_time;
- unsigned SMBgetatr_count; /* get file attributes */
- unsigned SMBgetatr_time;
- unsigned SMBsetatr_count; /* set file attributes */
- unsigned SMBsetatr_time;
- unsigned SMBread_count; /* read from file */
- unsigned SMBread_time;
- unsigned SMBwrite_count; /* write to file */
- unsigned SMBwrite_time;
- unsigned SMBlock_count; /* lock byte range */
- unsigned SMBlock_time;
- unsigned SMBunlock_count; /* unlock byte range */
- unsigned SMBunlock_time;
- unsigned SMBctemp_count; /* create temporary file */
- unsigned SMBctemp_time;
- /* SMBmknew stats are currently combined with SMBcreate */
- unsigned SMBmknew_count; /* make new file */
- unsigned SMBmknew_time;
- unsigned SMBchkpth_count; /* check directory path */
- unsigned SMBchkpth_time;
- unsigned SMBexit_count; /* process exit */
- unsigned SMBexit_time;
- unsigned SMBlseek_count; /* seek */
- unsigned SMBlseek_time;
- unsigned SMBlockread_count; /* Lock a range and read */
- unsigned SMBlockread_time;
- unsigned SMBwriteunlock_count; /* Unlock a range then write */
- unsigned SMBwriteunlock_time;
- unsigned SMBreadbraw_count; /* read a block of data with no smb header */
- unsigned SMBreadbraw_time;
- unsigned SMBreadBmpx_count; /* read block multiplexed */
- unsigned SMBreadBmpx_time;
- unsigned SMBreadBs_count; /* read block (secondary response) */
- unsigned SMBreadBs_time;
- unsigned SMBwritebraw_count; /* write a block of data with no smb header */
- unsigned SMBwritebraw_time;
- unsigned SMBwriteBmpx_count; /* write block multiplexed */
- unsigned SMBwriteBmpx_time;
- unsigned SMBwriteBs_count; /* write block (secondary request) */
- unsigned SMBwriteBs_time;
- unsigned SMBwritec_count; /* secondary write request */
- unsigned SMBwritec_time;
- unsigned SMBsetattrE_count; /* set file attributes expanded */
- unsigned SMBsetattrE_time;
- unsigned SMBgetattrE_count; /* get file attributes expanded */
- unsigned SMBgetattrE_time;
- unsigned SMBlockingX_count; /* lock/unlock byte ranges and X */
- unsigned SMBlockingX_time;
- unsigned SMBtrans_count; /* transaction - name, bytes in/out */
- unsigned SMBtrans_time;
- unsigned SMBtranss_count; /* transaction (secondary request/response) */
- unsigned SMBtranss_time;
- unsigned SMBioctl_count; /* IOCTL */
- unsigned SMBioctl_time;
- unsigned SMBioctls_count; /* IOCTL (secondary request/response) */
- unsigned SMBioctls_time;
- unsigned SMBcopy_count; /* copy */
- unsigned SMBcopy_time;
- unsigned SMBmove_count; /* move */
- unsigned SMBmove_time;
- unsigned SMBecho_count; /* echo */
- unsigned SMBecho_time;
- unsigned SMBwriteclose_count; /* write a file then close it */
- unsigned SMBwriteclose_time;
- unsigned SMBopenX_count; /* open and X */
- unsigned SMBopenX_time;
- unsigned SMBreadX_count; /* read and X */
- unsigned SMBreadX_time;
- unsigned SMBwriteX_count; /* write and X */
- unsigned SMBwriteX_time;
- unsigned SMBtrans2_count; /* TRANS2 protocol set */
- unsigned SMBtrans2_time;
- unsigned SMBtranss2_count; /* TRANS2 protocol set, secondary command */
- unsigned SMBtranss2_time;
- unsigned SMBfindclose_count; /* Terminate a TRANSACT2_FINDFIRST */
- unsigned SMBfindclose_time;
- unsigned SMBfindnclose_count; /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
- unsigned SMBfindnclose_time;
- unsigned SMBtcon_count; /* tree connect */
- unsigned SMBtcon_time;
- unsigned SMBtdis_count; /* tree disconnect */
- unsigned SMBtdis_time;
- unsigned SMBnegprot_count; /* negotiate protocol */
- unsigned SMBnegprot_time;
- unsigned SMBsesssetupX_count; /* Session Set Up & X (including User Logon) */
- unsigned SMBsesssetupX_time;
- unsigned SMBulogoffX_count; /* user logoff */
- unsigned SMBulogoffX_time;
- unsigned SMBtconX_count; /* tree connect and X*/
- unsigned SMBtconX_time;
- unsigned SMBdskattr_count; /* get disk attributes */
- unsigned SMBdskattr_time;
- unsigned SMBsearch_count; /* search directory */
- unsigned SMBsearch_time;
- /* SBMffirst stats combined with SMBsearch */
- unsigned SMBffirst_count; /* find first */
- unsigned SMBffirst_time;
- /* SBMfunique stats combined with SMBsearch */
- unsigned SMBfunique_count; /* find unique */
- unsigned SMBfunique_time;
- unsigned SMBfclose_count; /* find close */
- unsigned SMBfclose_time;
- unsigned SMBnttrans_count; /* NT transact */
- unsigned SMBnttrans_time;
- unsigned SMBnttranss_count; /* NT transact secondary */
- unsigned SMBnttranss_time;
- unsigned SMBntcreateX_count; /* NT create and X */
- unsigned SMBntcreateX_time;
- unsigned SMBntcancel_count; /* NT cancel */
- unsigned SMBntcancel_time;
- unsigned SMBntrename_count; /* NT rename file */
- unsigned SMBntrename_time;
- unsigned SMBsplopen_count; /* open print spool file */
- unsigned SMBsplopen_time;
- unsigned SMBsplwr_count; /* write to print spool file */
- unsigned SMBsplwr_time;
- unsigned SMBsplclose_count; /* close print spool file */
- unsigned SMBsplclose_time;
- unsigned SMBsplretq_count; /* return print queue */
- unsigned SMBsplretq_time;
- unsigned SMBsends_count; /* send single block message */
- unsigned SMBsends_time;
- unsigned SMBsendb_count; /* send broadcast message */
- unsigned SMBsendb_time;
- unsigned SMBfwdname_count; /* forward user name */
- unsigned SMBfwdname_time;
- unsigned SMBcancelf_count; /* cancel forward */
- unsigned SMBcancelf_time;
- unsigned SMBgetmac_count; /* get machine name */
- unsigned SMBgetmac_time;
- unsigned SMBsendstrt_count; /* send start of multi-block message */
- unsigned SMBsendstrt_time;
- unsigned SMBsendend_count; /* send end of multi-block message */
- unsigned SMBsendend_time;
- unsigned SMBsendtxt_count; /* send text of multi-block message */
- unsigned SMBsendtxt_time;
- unsigned SMBinvalid_count; /* invalid command */
- unsigned SMBinvalid_time;
-/* Pathworks setdir command */
- unsigned pathworks_setdir_count;
- unsigned pathworks_setdir_time;
-/* These are the TRANS2 sub commands */
- unsigned Trans2_open_count;
- unsigned Trans2_open_time;
- unsigned Trans2_findfirst_count;
- unsigned Trans2_findfirst_time;
- unsigned Trans2_findnext_count;
- unsigned Trans2_findnext_time;
- unsigned Trans2_qfsinfo_count;
- unsigned Trans2_qfsinfo_time;
- unsigned Trans2_setfsinfo_count;
- unsigned Trans2_setfsinfo_time;
- unsigned Trans2_qpathinfo_count;
- unsigned Trans2_qpathinfo_time;
- unsigned Trans2_setpathinfo_count;
- unsigned Trans2_setpathinfo_time;
- unsigned Trans2_qfileinfo_count;
- unsigned Trans2_qfileinfo_time;
- unsigned Trans2_setfileinfo_count;
- unsigned Trans2_setfileinfo_time;
- unsigned Trans2_fsctl_count;
- unsigned Trans2_fsctl_time;
- unsigned Trans2_ioctl_count;
- unsigned Trans2_ioctl_time;
- unsigned Trans2_findnotifyfirst_count;
- unsigned Trans2_findnotifyfirst_time;
- unsigned Trans2_findnotifynext_count;
- unsigned Trans2_findnotifynext_time;
- unsigned Trans2_mkdir_count;
- unsigned Trans2_mkdir_time;
- unsigned Trans2_session_setup_count;
- unsigned Trans2_session_setup_time;
- unsigned Trans2_get_dfs_referral_count;
- unsigned Trans2_get_dfs_referral_time;
- unsigned Trans2_report_dfs_inconsistancy_count;
- unsigned Trans2_report_dfs_inconsistancy_time;
-/* These are the NT transact sub commands. */
- unsigned NT_transact_create_count;
- unsigned NT_transact_create_time;
- unsigned NT_transact_ioctl_count;
- unsigned NT_transact_ioctl_time;
- unsigned NT_transact_set_security_desc_count;
- unsigned NT_transact_set_security_desc_time;
- unsigned NT_transact_notify_change_count;
- unsigned NT_transact_notify_change_time;
- unsigned NT_transact_rename_count;
- unsigned NT_transact_rename_time;
- unsigned NT_transact_query_security_desc_count;
- unsigned NT_transact_query_security_desc_time;
- unsigned NT_transact_get_user_quota_count;
- unsigned NT_transact_get_user_quota_time;
- unsigned NT_transact_set_user_quota_count;
- unsigned NT_transact_set_user_quota_time;
-/* These are ACL manipulation calls */
- unsigned get_nt_acl_count;
- unsigned get_nt_acl_time;
- unsigned fget_nt_acl_count;
- unsigned fget_nt_acl_time;
- unsigned set_nt_acl_count;
- unsigned set_nt_acl_time;
- unsigned fset_nt_acl_count;
- unsigned fset_nt_acl_time;
- unsigned chmod_acl_count;
- unsigned chmod_acl_time;
- unsigned fchmod_acl_count;
- unsigned fchmod_acl_time;
-/* These are nmbd stats */
- unsigned name_release_count;
- unsigned name_release_time;
- unsigned name_refresh_count;
- unsigned name_refresh_time;
- unsigned name_registration_count;
- unsigned name_registration_time;
- unsigned node_status_count;
- unsigned node_status_time;
- unsigned name_query_count;
- unsigned name_query_time;
- unsigned host_announce_count;
- unsigned host_announce_time;
- unsigned workgroup_announce_count;
- unsigned workgroup_announce_time;
- unsigned local_master_announce_count;
- unsigned local_master_announce_time;
- unsigned master_browser_announce_count;
- unsigned master_browser_announce_time;
- unsigned lm_host_announce_count;
- unsigned lm_host_announce_time;
- unsigned get_backup_list_count;
- unsigned get_backup_list_time;
- unsigned reset_browser_count;
- unsigned reset_browser_time;
- unsigned announce_request_count;
- unsigned announce_request_time;
- unsigned lm_announce_request_count;
- unsigned lm_announce_request_time;
- unsigned domain_logon_count;
- unsigned domain_logon_time;
- unsigned sync_browse_lists_count;
- unsigned sync_browse_lists_time;
- unsigned run_elections_count;
- unsigned run_elections_time;
- unsigned election_count;
- unsigned election_time;
};
struct profile_header {
@@ -402,10 +761,6 @@ struct profile_header {
extern struct profile_header *profile_h;
extern struct profile_stats *profile_p;
-extern struct timeval profile_starttime;
-extern struct timeval profile_endtime;
-extern struct timeval profile_starttime_nested;
-extern struct timeval profile_endtime_nested;
extern BOOL do_profile_flag;
extern BOOL do_profile_times;
@@ -491,8 +846,6 @@ static inline SMB_BIG_UINT profile_timestamp(void)
profile_timestamp() - __profstamp_##x); \
}
-#define START_PROFILE_NESTED(x) START_PROFILE(x)
-#define END_PROFILE_NESTED(x) END_PROFILE(x)
#else /* WITH_PROFILE */
@@ -501,10 +854,8 @@ static inline SMB_BIG_UINT profile_timestamp(void)
#define DO_PROFILE_DEC_INC(x,y)
#define DO_PROFILE_ADD(x,n)
#define START_PROFILE(x)
-#define START_PROFILE_NESTED(x)
#define START_PROFILE_BYTES(x,n)
#define END_PROFILE(x)
-#define END_PROFILE_NESTED(x)
#endif /* WITH_PROFILE */
diff --git a/source/include/socket_wrapper.h b/source/include/socket_wrapper.h
deleted file mode 100644
index d8815a25757..00000000000
--- a/source/include/socket_wrapper.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __SOCKET_WRAPPER_H__
-#define __SOCKET_WRAPPER_H__
-
-int swrap_socket(int domain, int type, int protocol);
-int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen);
-int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen);
-int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen);
-int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
-int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
-int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
-ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
-ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
-int swrap_close(int);
-
-#ifdef SOCKET_WRAPPER_REPLACE
-#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen)
-#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen)
-#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen)
-#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen)
-#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen)
-#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen)
-#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen)
-#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen)
-#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen)
-#define socket(domain,type,protocol) swrap_socket(domain,type,protocol)
-#define close(s) swrap_close(s)
-#endif
-
-#endif /* __SOCKET_WRAPPER_H__ */
diff --git a/source/include/trans2.h b/source/include/trans2.h
index 92c5a2e963f..5b9623e3d40 100644
--- a/source/include/trans2.h
+++ b/source/include/trans2.h
@@ -394,6 +394,8 @@ Offset Size Name
100 - end.
*/
+#define SMB_FILE_UNIX_BASIC_SIZE 100
+
/* UNIX filetype mappings. */
#define UNIX_TYPE_FILE 0
@@ -446,6 +448,13 @@ Offset Size Name
/* Only valid for setfileinfo */
#define SMB_SET_POSIX_LOCK 0x208
+/* The set info levels for POSIX path operations. */
+#define SMB_POSIX_PATH_OPEN 0x209
+#define SMB_POSIX_PATH_UNLINK 0x20A
+
+#define SMB_QUERY_FILE_UNIX_INFO2 0x20B /* UNIX File Info2 */
+#define SMB_SET_FILE_UNIX_INFO2 0x20B
+
/* Transact 2 Find First levels */
#define SMB_FIND_FILE_UNIX 0x202
@@ -477,6 +486,7 @@ Offset Size Name
#define CIFS_UNIX_EXTATTR_CAP 0x8 /* for support of chattr
(chflags) and lsattr */
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x10 /* Use POSIX pathnames on the wire. */
+#define CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP 0x20 /* We can cope with POSIX open/mkdir/unlink etc. */
#define SMB_QUERY_POSIX_FS_INFO 0x201
@@ -579,7 +589,7 @@ number of entries sent will be zero.
#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF
-/* Definition of SMB_SET_POSIX_LOCK */
+/* Definition of parameter block of SMB_SET_POSIX_LOCK */
/*
[2 bytes] lock_type - 0 = Read, 1 = Write, 2 = Unlock
[2 bytes] lock_flags - 1 = Wait (only valid for setlock)
@@ -602,4 +612,37 @@ number of entries sent will be zero.
#define POSIX_LOCK_TYPE_WRITE 1
#define POSIX_LOCK_TYPE_UNLOCK 2
+/* SMB_POSIX_PATH_OPEN "open_mode" definitions. */
+#define SMB_O_RDONLY 0x1
+#define SMB_O_WRONLY 0x2
+#define SMB_O_RDWR 0x4
+
+#define SMB_ACCMODE 0x7
+
+#define SMB_O_CREAT 0x10
+#define SMB_O_EXCL 0x20
+#define SMB_O_TRUNC 0x40
+#define SMB_O_APPEND 0x80
+#define SMB_O_SYNC 0x100
+#define SMB_O_DIRECTORY 0x200
+#define SMB_O_NOFOLLOW 0x400
+#define SMB_O_DIRECT 0x800
+
+/* Definition of request parameter block for SMB_POSIX_PATH_OPEN */
+/*
+ [4 bytes] flags (as smb_ntcreate_Flags).
+ [4 bytes] open_mode
+ [4 bytes] mode_t - same encoding as "Standard UNIX permissions" above.
+ [2 bytes] ret_info_level - optimization. Info level to be returned.
+*/
+
+/* Definition of reply data block for SMB_POSIX_PATH_OPEN */
+
+#define SMB_NO_INFO_LEVEL_RETURNED 0xFFFF
+
+/*
+ [2 bytes] reply info level - as requested or 0xFFFF if not available.
+ [n bytes] - info level reply - if available.
+*/
+
#endif
diff --git a/source/include/util_tdb.h b/source/include/util_tdb.h
new file mode 100644
index 00000000000..a8def46e441
--- /dev/null
+++ b/source/include/util_tdb.h
@@ -0,0 +1,76 @@
+/*
+ Unix SMB/CIFS implementation.
+ tdb utility functions
+ Copyright (C) Andrew Tridgell 1999
+
+ 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 __TDBUTIL_H__
+#define __TDBUTIL_H__
+
+#include "tdb.h"
+
+#ifndef _BOOL
+typedef int BOOL;
+#define _BOOL
+#endif
+
+/* single node of a list returned by tdb_search_keys */
+typedef struct keys_node
+{
+ struct keys_node *prev, *next;
+ TDB_DATA node_key;
+} TDB_LIST_NODE;
+
+struct tdb_wrap {
+ struct tdb_context *tdb;
+ const char *name;
+ struct tdb_wrap *next, *prev;
+};
+
+TDB_LIST_NODE *tdb_search_keys(struct tdb_context*, const char*);
+void tdb_search_list_free(TDB_LIST_NODE*);
+int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val);
+int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval);
+int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
+ int timeout);
+void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval);
+int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
+ unsigned int timeout);
+void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval);
+int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr);
+int tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value);
+int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v);
+int tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value);
+int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf,
+ void *state);
+int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags);
+TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr);
+int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr);
+struct tdb_context *tdb_open_log(const char *name, int hash_size,
+ int tdb_flags, int open_flags, mode_t mode);
+int tdb_unpack(char *buf, int bufsize, const char *fmt, ...);
+size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...);
+TDB_DATA make_tdb_data(const char *dptr, size_t dsize);
+TDB_DATA string_tdb_data(const char *string);
+int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+ int flag);
+int tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr,
+ uint32 *oldval, uint32 change_val);
+int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key,
+ unsigned int timeout);
+
+#endif /* __TDBUTIL_H__ */
diff --git a/source/include/vfs.h b/source/include/vfs.h
index fb99d824125..2d04a374c4c 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -62,7 +62,12 @@
/* Changed to version 14 as we had to change DIR to SMB_STRUCT_DIR. JRA */
/* Changed to version 15 as we added the statvfs call. JRA */
/* Changed to version 16 as we added the getlock call. JRA */
-#define SMB_VFS_INTERFACE_VERSION 16
+/* Changed to version 17 as we removed redundant connection_struct parameters. --jpeach */
+/* Changed to version 18 to add fsp parameter to the open call -- jpeach
+ Also include kernel_flock call - jmcd */
+/* Changed to version 19, kernel change notify has been merged
+ Also included linux setlease call - jmcd */
+#define SMB_VFS_INTERFACE_VERSION 19
/* to bug old modules which are trying to compile with the old functions */
@@ -142,12 +147,15 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_UTIME,
SMB_VFS_OP_FTRUNCATE,
SMB_VFS_OP_LOCK,
+ SMB_VFS_OP_KERNEL_FLOCK,
+ SMB_VFS_OP_LINUX_SETLEASE,
SMB_VFS_OP_GETLOCK,
SMB_VFS_OP_SYMLINK,
SMB_VFS_OP_READLINK,
SMB_VFS_OP_LINK,
SMB_VFS_OP_MKNOD,
SMB_VFS_OP_REALPATH,
+ SMB_VFS_OP_NOTIFY_WATCH,
/* NT ACL operations. */
@@ -219,29 +227,29 @@ struct vfs_ops {
struct vfs_fn_pointers {
/* Disk operations */
- int (*connect_fn)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *service, const char *user);
- void (*disconnect)(struct vfs_handle_struct *handle, struct connection_struct *conn);
- SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
+ int (*connect_fn)(struct vfs_handle_struct *handle, const char *service, const char *user);
+ void (*disconnect)(struct vfs_handle_struct *handle);
+ SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
- int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
- int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
+ int (*get_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
+ int (*set_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels);
- int (*statvfs)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf);
+ int (*statvfs)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf);
/* Directory operations */
- SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attributes);
- SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
- void (*seekdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset);
- long (*telldir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
- void (*rewind_dir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dirp);
- int (*mkdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode);
- int (*rmdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
- int (*closedir)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *dir);
+ SMB_STRUCT_DIR *(*opendir)(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attributes);
+ SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+ void (*seekdir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset);
+ long (*telldir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+ void (*rewind_dir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp);
+ int (*mkdir)(struct vfs_handle_struct *handle, const char *path, mode_t mode);
+ int (*rmdir)(struct vfs_handle_struct *handle, const char *path);
+ int (*closedir)(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *dir);
/* File operations */
- int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode);
+ int (*open)(struct vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
int (*close_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n);
ssize_t (*pread)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n, SMB_OFF_T offset);
@@ -249,27 +257,36 @@ struct vfs_ops {
ssize_t (*pwrite)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset);
SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence);
ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
- int (*rename)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname);
+ int (*rename)(struct vfs_handle_struct *handle, const char *oldname, const char *newname);
int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
- int (*stat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf);
+ int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf);
int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf);
- int (*lstat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf);
- int (*unlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
- int (*chmod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode);
+ int (*lstat)(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf);
+ int (*unlink)(struct vfs_handle_struct *handle, const char *path);
+ int (*chmod)(struct vfs_handle_struct *handle, const char *path, mode_t mode);
int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode);
- int (*chown)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid);
+ int (*chown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid);
int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
- int (*chdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
- char *(*getwd)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *buf);
- int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times);
+ int (*chdir)(struct vfs_handle_struct *handle, const char *path);
+ char *(*getwd)(struct vfs_handle_struct *handle, char *buf);
+ int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times);
int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
+ int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode);
+ int (*linux_setlease)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int leasetype);
BOOL (*getlock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
- int (*symlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
- int (*readlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *buf, size_t bufsiz);
- int (*link)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
- int (*mknod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev);
- char *(*realpath)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *resolved_path);
+ int (*symlink)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath);
+ int (*readlink)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz);
+ int (*link)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath);
+ int (*mknod)(struct vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev);
+ char *(*realpath)(struct vfs_handle_struct *handle, const char *path, char *resolved_path);
+ NTSTATUS (*notify_watch)(struct vfs_handle_struct *handle,
+ struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data, void *handle_p);
/* NT ACL operations. */
@@ -280,44 +297,44 @@ struct vfs_ops {
/* POSIX ACL operations. */
- int (*chmod_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, mode_t mode);
+ int (*chmod_acl)(struct vfs_handle_struct *handle, const char *name, mode_t mode);
int (*fchmod_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode);
- int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
- int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
- int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
- void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d);
- SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type);
+ int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
+ int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
+ int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
+ void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d);
+ SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type);
SMB_ACL_T (*sys_acl_get_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
- int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset);
- int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
- char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen);
- SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, struct connection_struct *conn, int count);
- int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
- int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
- int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual);
- int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
- int (*sys_acl_valid)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl );
- int (*sys_acl_set_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
+ int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset);
+ int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+ char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, SMB_ACL_T theacl, ssize_t *plen);
+ SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, int count);
+ int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
+ int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
+ int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, void *qual);
+ int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
+ int (*sys_acl_valid)(struct vfs_handle_struct *handle, SMB_ACL_T theacl );
+ int (*sys_acl_set_file)(struct vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
int (*sys_acl_set_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_ACL_T theacl);
- int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path);
- int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
- int (*sys_acl_free_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *text);
- int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T posix_acl);
- int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype);
+ int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, const char *path);
+ int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+ int (*sys_acl_free_text)(struct vfs_handle_struct *handle, char *text);
+ int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, SMB_ACL_T posix_acl);
+ int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, void *qualifier, SMB_ACL_TAG_T tagtype);
/* EA operations. */
- ssize_t (*getxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size);
- ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size);
+ ssize_t (*getxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size);
+ ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size);
ssize_t (*fgetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size);
- ssize_t (*listxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size);
- ssize_t (*llistxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size);
+ ssize_t (*listxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size);
+ ssize_t (*llistxattr)(struct vfs_handle_struct *handle, const char *path, char *list, size_t size);
ssize_t (*flistxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size);
- int (*removexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name);
- int (*lremovexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name);
+ int (*removexattr)(struct vfs_handle_struct *handle, const char *path, const char *name);
+ int (*lremovexattr)(struct vfs_handle_struct *handle, const char *path, const char *name);
int (*fremovexattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name);
- int (*setxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags);
- int (*lsetxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags);
+ int (*setxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags);
+ int (*lsetxattr)(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags);
int (*fsetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name, const void *value, size_t size, int flags);
/* aio operations */
@@ -378,12 +395,15 @@ struct vfs_ops {
struct vfs_handle_struct *utime;
struct vfs_handle_struct *ftruncate;
struct vfs_handle_struct *lock;
+ struct vfs_handle_struct *kernel_flock;
+ struct vfs_handle_struct *linux_setlease;
struct vfs_handle_struct *getlock;
struct vfs_handle_struct *symlink;
struct vfs_handle_struct *readlink;
struct vfs_handle_struct *link;
struct vfs_handle_struct *mknod;
struct vfs_handle_struct *realpath;
+ struct vfs_handle_struct *notify_watch;
/* NT ACL operations. */
@@ -530,6 +550,14 @@ typedef struct vfs_statvfs_struct {
/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
} vfs_statvfs_struct;
+#define VFS_ADD_FSP_EXTENSION(handle, fsp, type) \
+ vfs_add_fsp_extension_notype(handle, (fsp), sizeof(type))
+
+#define VFS_FETCH_FSP_EXTENSION(handle, fsp) \
+ vfs_fetch_fsp_extension(handle, (fsp))
+
+#define VFS_REMOVE_FSP_EXTENSION(handle, fsp) \
+ vfs_remove_fsp_extension((handle), (fsp))
#define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \
if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \
@@ -562,6 +590,7 @@ typedef struct vfs_statvfs_struct {
#define SMB_VFS_OP(x) ((void *) x)
+#define DEFAULT_VFS_MODULE_NAME "/[Default VFS]/"
#include "vfs_macros.h"
diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h
index e08b386a6ac..f50da3a02b5 100644
--- a/source/include/vfs_macros.h
+++ b/source/include/vfs_macros.h
@@ -28,26 +28,26 @@
********************************************************************/
/* Disk operations */
-#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect, (conn)))
-#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect_fn((conn)->vfs.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect))
+#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (qtype), (id), (qt)))
#define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (path), (statbuf)))
/* Directory operations */
-#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (conn), (dirp)))
-#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (conn), (dirp), (offset)))
-#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (conn), (dirp)))
-#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (conn), (dirp)))
-#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (conn), (path)))
-#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, (conn), dir))
+#define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (dirp)))
+#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (dirp)))
+#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewind_dir((conn)->vfs.handles.rewind_dir, (dirp)))
+#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(path), (mode)))
+#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (path)))
+#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, dir))
/* File operations */
-#define SMB_VFS_OPEN(conn, fname, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (fname), (fsp), (flags), (mode)))
#define SMB_VFS_CLOSE(fsp, fd) ((fsp)->conn->vfs.ops.close_fn((fsp)->conn->vfs.handles.close_hnd, (fsp), (fd)))
#define SMB_VFS_READ(fsp, fd, data, n) ((fsp)->conn->vfs.ops.read((fsp)->conn->vfs.handles.read, (fsp), (fd), (data), (n)))
#define SMB_VFS_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pread((fsp)->conn->vfs.handles.pread, (fsp), (fd), (data), (n), (off)))
@@ -55,27 +55,30 @@
#define SMB_VFS_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pwrite((fsp)->conn->vfs.handles.pwrite, (fsp), (fd), (data), (n), (off)))
#define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence)))
#define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (old), (new)))
#define SMB_VFS_FSYNC(fsp, fd) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf)))
#define SMB_VFS_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (conn), (path)))
-#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (path)))
+#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (path), (mode)))
#define SMB_VFS_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod((fsp)->conn->vfs.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (path), (uid), (gid)))
#define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (conn), (path)))
-#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (conn), (buf)))
-#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path)))
+#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf)))
+#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times)))
#define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_KERNEL_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs.ops.kernel_flock((fsp)->conn->vfs.handles.kernel_flock, (fsp), (fd), (share_mode)))
+#define SMB_VFS_LINUX_SETLEASE(fsp, fd, leasetype) ((fsp)->conn->vfs.ops.linux_setlease((fsp)->conn->vfs.handles.linux_setlease, (fsp), (fd), (leasetype)))
#define SMB_VFS_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs.ops.getlock((fsp)->conn->vfs.handles.getlock, (fsp), (fd) ,(poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path)))
+#define SMB_VFS_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs.ops.notify_watch((conn)->vfs.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
/* NT ACL operations. */
#define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
@@ -84,44 +87,44 @@
#define SMB_VFS_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs.ops.set_nt_acl((fsp)->conn->vfs.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
/* POSIX ACL operations. */
-#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (name), (mode)))
#define SMB_VFS_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod_acl((fsp)->conn->vfs.handles.chmod_acl, (fsp), (fd), (mode)))
-#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (path_p), (type)))
#define SMB_VFS_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs.ops.sys_acl_get_fd((fsp)->conn->vfs.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (count)))
+#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (name), (acltype), (theacl)))
#define SMB_VFS_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs.ops.sys_acl_set_fd((fsp)->conn->vfs.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
/* EA operations. */
-#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(path),(name),(value),(size)))
#define SMB_VFS_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs.ops.fgetxattr((fsp)->conn->vfs.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(path),(list),(size)))
#define SMB_VFS_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs.ops.flistxattr((fsp)->conn->vfs.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(path),(name)))
+#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(path),(name)))
#define SMB_VFS_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs.ops.fremovexattr((fsp)->conn->vfs.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(path),(name),(value),(size),(flags)))
#define SMB_VFS_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs.ops.fsetxattr((fsp)->conn->vfs.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
/* AIO operations. */
@@ -140,26 +143,26 @@
********************************************************************/
/* Disk operations */
-#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect, (conn)))
-#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect_fn((conn)->vfs_opaque.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect))
+#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (qtype), (id), (qt)))
#define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (path), (statbuf)))
/* Directory operations */
-#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (conn), (dirp)))
-#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (conn), (dirp), (offset)))
-#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (conn), (dirp)))
-#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (conn), (dirp)))
-#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (conn), (path)))
-#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, (conn), dir))
+#define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (dirp)))
+#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (dirp)))
+#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewind_dir((conn)->vfs_opaque.handles.rewind_dir, (dirp)))
+#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(path), (mode)))
+#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (path)))
+#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, dir))
/* File operations */
-#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_OPAQUE_OPEN(conn, fname, fsp, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (fname), (fsp), (flags), (mode)))
#define SMB_VFS_OPAQUE_CLOSE(fsp, fd) ((fsp)->conn->vfs_opaque.ops.close_fn((fsp)->conn->vfs_opaque.handles.close_hnd, (fsp), (fd)))
#define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.read((fsp)->conn->vfs_opaque.handles.read, (fsp), (fd), (data), (n)))
#define SMB_VFS_OPAQUE_PREAD(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pread((fsp)->conn->vfs_opaque.handles.pread, (fsp), (fd), (data), (n), (off)))
@@ -167,27 +170,30 @@
#define SMB_VFS_OPAQUE_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pwrite((fsp)->conn->vfs_opaque.handles.pwrite, (fsp), (fd), (data), (n), (off)))
#define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence)))
#define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (old), (new)))
#define SMB_VFS_OPAQUE_FSYNC(fsp, fd) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf)))
#define SMB_VFS_OPAQUE_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (conn), (path)))
-#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (path)))
+#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (path), (mode)))
#define SMB_VFS_OPAQUE_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod((fsp)->conn->vfs_opaque.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (path), (uid), (gid)))
#define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (conn), (path)))
-#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (conn), (buf)))
-#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path)))
+#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf)))
+#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times)))
#define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_OPAQUE_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.kernel_flock, (fsp), (fd), (share_mode)))
+#define SMB_VFS_OPAQUE_LINUX_SETLEASE(fsp, fd, leasetype) ((fsp)->conn->vfs_opaque.ops.linux_setlease((fsp)->conn->vfs_opaque.handles.linux_setlease, (fsp), (fd), (leasetype)))
#define SMB_VFS_OPAQUE_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs_opaque.ops.getlock((fsp)->conn->vfs_opaque.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path)))
+#define SMB_VFS_OPAQUE_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_opaque.ops.notify_watch((conn)->vfs_opaque.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
/* NT ACL operations. */
#define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
@@ -196,44 +202,44 @@
#define SMB_VFS_OPAQUE_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs_opaque.ops.set_nt_acl((fsp)->conn->vfs_opaque.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
/* POSIX ACL operations. */
-#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (name), (mode)))
#define SMB_VFS_OPAQUE_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod_acl((fsp)->conn->vfs_opaque.handles.chmod_acl, (fsp), (fd), (mode)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (path_p), (type)))
#define SMB_VFS_OPAQUE_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs_opaque.ops.sys_acl_get_fd((fsp)->conn->vfs_opaque.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (count)))
+#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (name), (acltype), (theacl)))
#define SMB_VFS_OPAQUE_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs_opaque.ops.sys_acl_set_fd((fsp)->conn->vfs_opaque.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
/* EA operations. */
-#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(path),(name),(value),(size)))
#define SMB_VFS_OPAQUE_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs_opaque.ops.fgetxattr((fsp)->conn->vfs_opaque.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(path),(list),(size)))
#define SMB_VFS_OPAQUE_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs_opaque.ops.flistxattr((fsp)->conn->vfs_opaque.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(path),(name)))
+#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(path),(name)))
#define SMB_VFS_OPAQUE_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs_opaque.ops.fremovexattr((fsp)->conn->vfs_opaque.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(path),(name),(value),(size),(flags)))
#define SMB_VFS_OPAQUE_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs_opaque.ops.fsetxattr((fsp)->conn->vfs_opaque.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
/* AIO operations. */
@@ -252,27 +258,27 @@
********************************************************************/
/* Disk operations */
-#define SMB_VFS_NEXT_CONNECT(handle, conn, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (conn), (service), (user)))
-#define SMB_VFS_NEXT_DISCONNECT(handle, conn) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect, (conn)))
-#define SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize)))
-#define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt)))
-#define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt)))
+#define SMB_VFS_NEXT_CONNECT(handle, service, user) ((handle)->vfs_next.ops.connect_fn((handle)->vfs_next.handles.connect_hnd, (service), (user)))
+#define SMB_VFS_NEXT_DISCONNECT(handle) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect))
+#define SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (path), (small_query), (bsize), (dfree), (dsize)))
+#define SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (qtype), (id), (qt)))
+#define SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (qtype), (id), (qt)))
#define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
-#define SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (conn), (path), (statbuf)))
+#define SMB_VFS_NEXT_STATVFS(handle, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (path), (statbuf)))
/* Directory operations */
-#define SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname), (mask), (attr)))
-#define SMB_VFS_NEXT_READDIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp)))
-#define SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (conn), (dirp), (offset)))
-#define SMB_VFS_NEXT_TELLDIR(handle, conn, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (conn), (dirp)))
-#define SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (conn), (dirp)))
-#define SMB_VFS_NEXT_DIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp)))
-#define SMB_VFS_NEXT_MKDIR(handle, conn, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(conn), (path), (mode)))
-#define SMB_VFS_NEXT_RMDIR(handle, conn, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (conn), (path)))
-#define SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, (conn), dir))
+#define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (fname), (mask), (attr)))
+#define SMB_VFS_NEXT_READDIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (dirp), (offset)))
+#define SMB_VFS_NEXT_TELLDIR(handle, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (dirp)))
+#define SMB_VFS_NEXT_REWINDDIR(handle, dirp) ((handle)->vfs_next.ops.rewind_dir((handle)->vfs_next.handles.rewind_dir, (dirp)))
+#define SMB_VFS_NEXT_DIR(handle, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (dirp)))
+#define SMB_VFS_NEXT_MKDIR(handle, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(path), (mode)))
+#define SMB_VFS_NEXT_RMDIR(handle, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (path)))
+#define SMB_VFS_NEXT_CLOSEDIR(handle, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, dir))
/* File operations */
-#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (conn), (fname), (flags), (mode)))
+#define SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (fname), (fsp), (flags), (mode)))
#define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) ((handle)->vfs_next.ops.close_fn((handle)->vfs_next.handles.close_hnd, (fsp), (fd)))
#define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.read((handle)->vfs_next.handles.read, (fsp), (fd), (data), (n)))
#define SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pread((handle)->vfs_next.handles.pread, (fsp), (fd), (data), (n), (off)))
@@ -280,27 +286,30 @@
#define SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pwrite((handle)->vfs_next.handles.pwrite, (fsp), (fd), (data), (n), (off)))
#define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence)))
#define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
-#define SMB_VFS_NEXT_RENAME(handle, conn, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (conn), (old), (new)))
+#define SMB_VFS_NEXT_RENAME(handle, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (old), (new)))
#define SMB_VFS_NEXT_FSYNC(handle, fsp, fd) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp), (fd)))
-#define SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (conn), (fname), (sbuf)))
+#define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf)))
#define SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp) ,(fd) ,(sbuf)))
-#define SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (conn), (path), (sbuf)))
-#define SMB_VFS_NEXT_UNLINK(handle, conn, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (conn), (path)))
-#define SMB_VFS_NEXT_CHMOD(handle, conn, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (conn), (path), (mode)))
+#define SMB_VFS_NEXT_LSTAT(handle, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (path), (sbuf)))
+#define SMB_VFS_NEXT_UNLINK(handle, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (path)))
+#define SMB_VFS_NEXT_CHMOD(handle, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (path), (mode)))
#define SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod((handle)->vfs_next.handles.fchmod, (fsp), (fd), (mode)))
-#define SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (conn), (path), (uid), (gid)))
+#define SMB_VFS_NEXT_CHOWN(handle, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (path), (uid), (gid)))
#define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid)))
-#define SMB_VFS_NEXT_CHDIR(handle, conn, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (conn), (path)))
-#define SMB_VFS_NEXT_GETWD(handle, conn, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (conn), (buf)))
-#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times)))
+#define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path)))
+#define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf)))
+#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times)))
#define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode)((handle)->vfs_next.ops.kernel_flock((handle)->vfs_next.handles.kernel_flock, (fsp), (fd), (share_mode)))
+#define SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, fd, leasetype)((handle)->vfs_next.ops.linux_setlease((handle)->vfs_next.handles.linux_setlease, (fsp), (fd), (leasetype)))
#define SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid) ((handle)->vfs_next.ops.getlock((handle)->vfs_next.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
-#define SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (conn), (oldpath), (newpath)))
-#define SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (conn), (path), (buf), (bufsiz)))
-#define SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (conn), (oldpath), (newpath)))
-#define SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (conn), (path), (mode), (dev)))
-#define SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (conn), (path), (resolved_path)))
+#define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (oldpath), (newpath)))
+#define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (path), (buf), (bufsiz)))
+#define SMB_VFS_NEXT_LINK(handle, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (oldpath), (newpath)))
+#define SMB_VFS_NEXT_MKNOD(handle, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (path), (mode), (dev)))
+#define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path)))
+#define SMB_VFS_NEXT_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_next.ops.notify_watch((conn)->vfs_next.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
/* NT ACL operations. */
#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
@@ -309,44 +318,44 @@
#define SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd) ((handle)->vfs_next.ops.set_nt_acl((handle)->vfs_next.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd)))
/* POSIX ACL operations. */
-#define SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (conn), (name), (mode)))
+#define SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (name), (mode)))
#define SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod_acl((handle)->vfs_next.handles.chmod_acl, (fsp), (fd), (mode)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (conn), (entry_d)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (conn), (path_p), (type)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (theacl), (entry_id), (entry_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (entry_d), (tag_type_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (entry_d), (permset_p)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (entry_d)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (path_p), (type)))
#define SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, fd) ((handle)->vfs_next.ops.sys_acl_get_fd((handle)->vfs_next.handles.sys_acl_get_fd, (fsp), (fd)))
-#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (conn), (permset)))
-#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (conn), (permset), (perm)))
-#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (conn), (theacl), (plen)))
-#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (conn), (count)))
-#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (conn), (pacl), (pentry)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (conn), (entry), (qual)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (conn), (entry), (permset)))
-#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (conn), (theacl)))
-#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl)))
+#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (permset)))
+#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (permset), (perm)))
+#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (theacl), (plen)))
+#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (count)))
+#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (pacl), (pentry)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (entry), (tagtype)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (entry), (qual)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (entry), (permset)))
+#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (theacl)))
+#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (name), (acltype), (theacl)))
#define SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, fd, theacl) ((handle)->vfs_next.ops.sys_acl_set_fd((handle)->vfs_next.handles.sys_acl_set_fd, (fsp), (fd), (theacl)))
-#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (conn), (path)))
-#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (conn), (permset), (perm)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (conn), (text)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (conn), (posix_acl)))
-#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype)))
+#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (path)))
+#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (permset), (perm)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (text)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (posix_acl)))
+#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (qualifier), (tagtype)))
/* EA operations. */
-#define SMB_VFS_NEXT_GETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(conn),(path),(name),(value),(size)))
-#define SMB_VFS_NEXT_LGETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(conn),(path),(name),(value),(size)))
+#define SMB_VFS_NEXT_GETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(path),(name),(value),(size)))
+#define SMB_VFS_NEXT_LGETXATTR(handle,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(path),(name),(value),(size)))
#define SMB_VFS_NEXT_FGETXATTR(handle,fsp,fd,name,value,size) ((handle)->vfs_next.ops.fgetxattr((handle)->vfs_next.handles.fgetxattr,(fsp),(fd),(name),(value),(size)))
-#define SMB_VFS_NEXT_LISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(conn),(path),(list),(size)))
-#define SMB_VFS_NEXT_LLISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(conn),(path),(list),(size)))
+#define SMB_VFS_NEXT_LISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(path),(list),(size)))
+#define SMB_VFS_NEXT_LLISTXATTR(handle,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(path),(list),(size)))
#define SMB_VFS_NEXT_FLISTXATTR(handle,fsp,fd,list,size) ((handle)->vfs_next.ops.flistxattr((handle)->vfs_next.handles.flistxattr,(fsp),(fd),(list),(size)))
-#define SMB_VFS_NEXT_REMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(conn),(path),(name)))
-#define SMB_VFS_NEXT_LREMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(conn),(path),(name)))
+#define SMB_VFS_NEXT_REMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(path),(name)))
+#define SMB_VFS_NEXT_LREMOVEXATTR(handle,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(path),(name)))
#define SMB_VFS_NEXT_FREMOVEXATTR(handle,fsp,fd,name) ((handle)->vfs_next.ops.fremovexattr((handle)->vfs_next.handles.fremovexattr,(fsp),(fd),(name)))
-#define SMB_VFS_NEXT_SETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(conn),(path),(name),(value),(size),(flags)))
-#define SMB_VFS_NEXT_LSETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags)))
+#define SMB_VFS_NEXT_SETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(path),(name),(value),(size),(flags)))
+#define SMB_VFS_NEXT_LSETXATTR(handle,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(path),(name),(value),(size),(flags)))
#define SMB_VFS_NEXT_FSETXATTR(handle,fsp,fd,name,value,size,flags) ((handle)->vfs_next.ops.fsetxattr((handle)->vfs_next.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags)))
/* AIO operations. */
diff --git a/source/iniparser/src/dictionary.c b/source/iniparser/src/dictionary.c
index 4381b9cb780..edbd6f9a353 100644
--- a/source/iniparser/src/dictionary.c
+++ b/source/iniparser/src/dictionary.c
@@ -114,11 +114,13 @@ dictionary * dictionary_new(int size)
/* If no size was specified, allocate space for DICTMINSZ */
if (size<DICTMINSZ) size=DICTMINSZ ;
- d = calloc(1, sizeof(dictionary));
+ if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
+ return NULL;
+ }
d->size = size ;
- d->val = calloc(size, sizeof(char*));
- d->key = calloc(size, sizeof(char*));
- d->hash = calloc(size, sizeof(unsigned));
+ d->val = (char **)calloc(size, sizeof(char*));
+ d->key = (char **)calloc(size, sizeof(char*));
+ d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
return d ;
}
@@ -316,9 +318,9 @@ void dictionary_set(dictionary * d, char * key, char * val)
if (d->n==d->size) {
/* Reached maximum size: reallocate blackboard */
- d->val = mem_double(d->val, d->size * sizeof(char*)) ;
- d->key = mem_double(d->key, d->size * sizeof(char*)) ;
- d->hash = mem_double(d->hash, d->size * sizeof(unsigned)) ;
+ d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ;
+ d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ;
+ d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
/* Double size */
d->size *= 2 ;
@@ -355,6 +357,10 @@ void dictionary_unset(dictionary * d, char * key)
unsigned hash ;
int i ;
+ if (key == NULL) {
+ return;
+ }
+
hash = dictionary_hash(key);
for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL)
diff --git a/source/iniparser/src/iniparser.c b/source/iniparser/src/iniparser.c
index 0c06ab364b1..0cb452b2655 100644
--- a/source/iniparser/src/iniparser.c
+++ b/source/iniparser/src/iniparser.c
@@ -230,7 +230,7 @@ void iniparser_dump_ini(dictionary * d, FILE * f)
iniparser_getstring() instead.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstr(dictionary * d, char * key)
+char * iniparser_getstr(dictionary * d, const char * key)
{
return iniparser_getstring(d, key, NULL);
}
@@ -251,7 +251,7 @@ char * iniparser_getstr(dictionary * d, char * key)
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, char * key, char * def)
+char * iniparser_getstring(dictionary * d, const char * key, char * def)
{
char * lc_key ;
char * sval ;
@@ -259,7 +259,9 @@ char * iniparser_getstring(dictionary * d, char * key, char * def)
if (d==NULL || key==NULL)
return def ;
- lc_key = strdup(strlwc(key));
+ if (!(lc_key = strdup(strlwc(key)))) {
+ return NULL;
+ }
sval = dictionary_get(d, lc_key, def);
free(lc_key);
return sval ;
@@ -280,7 +282,7 @@ char * iniparser_getstring(dictionary * d, char * key, char * def)
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, char * key, int notfound)
+int iniparser_getint(dictionary * d, const char * key, int notfound)
{
char * str ;
@@ -346,7 +348,7 @@ double iniparser_getdouble(dictionary * d, char * key, double notfound)
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, char * key, int notfound)
+int iniparser_getboolean(dictionary * d, const char * key, int notfound)
{
char * c ;
int ret ;
@@ -442,7 +444,7 @@ void iniparser_unset(dictionary * ini, char * entry)
*/
/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(char * ininame)
+dictionary * iniparser_load(const char * ininame)
{
dictionary * d ;
char lin[ASCIILINESZ+1];
@@ -462,7 +464,10 @@ dictionary * iniparser_load(char * ininame)
/*
* Initialize a new dictionary entry
*/
- d = dictionary_new(0);
+ if (!(d = dictionary_new(0))) {
+ fclose(ini);
+ return NULL;
+ }
lineno = 0 ;
while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
lineno++ ;
diff --git a/source/iniparser/src/iniparser.h b/source/iniparser/src/iniparser.h
index 98e8b33b781..2df8ffe8374 100644
--- a/source/iniparser/src/iniparser.h
+++ b/source/iniparser/src/iniparser.h
@@ -123,7 +123,7 @@ void iniparser_dump(dictionary * d, FILE * f);
iniparser_getstring() instead.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstr(dictionary * d, char * key);
+char * iniparser_getstr(dictionary * d, const char * key);
/*-------------------------------------------------------------------------*/
@@ -141,7 +141,7 @@ char * iniparser_getstr(dictionary * d, char * key);
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, char * key, char * def);
+char * iniparser_getstring(dictionary * d, const char * key, char * def);
/*-------------------------------------------------------------------------*/
/**
@@ -156,7 +156,7 @@ char * iniparser_getstring(dictionary * d, char * key, char * def);
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, char * key, int notfound);
+int iniparser_getint(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
@@ -205,7 +205,7 @@ double iniparser_getdouble(dictionary * d, char * key, double notfound);
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, char * key, int notfound);
+int iniparser_getboolean(dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
@@ -264,7 +264,7 @@ int iniparser_find_entry(dictionary * ini, char * entry) ;
The returned dictionary must be freed using iniparser_freedict().
*/
/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(char * ininame);
+dictionary * iniparser_load(const char * ininame);
/*-------------------------------------------------------------------------*/
/**
diff --git a/source/iniparser/src/strlib.c b/source/iniparser/src/strlib.c
index 3bfddaaebe2..b954a36cf79 100644
--- a/source/iniparser/src/strlib.c
+++ b/source/iniparser/src/strlib.c
@@ -51,7 +51,7 @@
*/
/*--------------------------------------------------------------------------*/
-char * strlwc(char * s)
+char * strlwc(const char * s)
{
static char l[ASCIILINESZ+1];
int i ;
diff --git a/source/iniparser/src/strlib.h b/source/iniparser/src/strlib.h
index 8d8f15fcf0a..39ca26f1df0 100644
--- a/source/iniparser/src/strlib.h
+++ b/source/iniparser/src/strlib.h
@@ -45,7 +45,7 @@
allocated, it will be modified at each function call (not re-entrant).
*/
/*--------------------------------------------------------------------------*/
-char * strlwc(char * s);
+char * strlwc(const char * s);
/*-------------------------------------------------------------------------*/
/**
diff --git a/source/intl/lang_tdb.c b/source/intl/lang_tdb.c
index 016f64af52a..ddb3d4d65e3 100644
--- a/source/intl/lang_tdb.c
+++ b/source/intl/lang_tdb.c
@@ -197,7 +197,7 @@ const char *lang_msg(const char *msgid)
count++;
}
- if (!(msgid_quoted = SMB_MALLOC(strlen(msgid) + count + 1)))
+ if (!(msgid_quoted = (char *)SMB_MALLOC(strlen(msgid) + count + 1)))
return msgid;
/* string_sub() is unsuitable here as it replaces some punctuation
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index d4e585f74f6..f4008457ac1 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -28,7 +28,6 @@ static TDB_CONTEXT *tdb;
* ldap directly) - gd */
#define DATABASE_VERSION 3
-#define AP_LASTSET "LAST_CACHE_UPDATE"
#define AP_TTL 60
@@ -84,28 +83,24 @@ static const struct ap_table account_policy_names[] = {
{0, NULL, 0, "", NULL}
};
-char *account_policy_names_list(void)
-{
- char *nl, *p;
- int i;
- size_t len = 0;
+void account_policy_names_list(const char ***names, int *num_names)
+{
+ const char **nl;
+ int i, count;
- for (i=0; account_policy_names[i].string; i++) {
- len += strlen(account_policy_names[i].string) + 1;
+ for (count=0; account_policy_names[count].string; count++) {
}
- len++;
- nl = SMB_MALLOC(len);
+ nl = SMB_MALLOC_ARRAY(const char *, count);
if (!nl) {
- return NULL;
+ *num_names = 0;
+ return;
}
- p = nl;
for (i=0; account_policy_names[i].string; i++) {
- memcpy(p, account_policy_names[i].string, strlen(account_policy_names[i].string) + 1);
- p[strlen(account_policy_names[i].string)] = '\n';
- p += strlen(account_policy_names[i].string) + 1;
+ nl[i] = account_policy_names[i].string;
}
- *p = '\0';
- return nl;
+ *num_names = count;
+ *names = nl;
+ return;
}
/****************************************************************************
@@ -169,50 +164,6 @@ int account_policy_name_to_fieldnum(const char *name)
}
/*****************************************************************************
-Update LAST-Set counter inside the cache
-*****************************************************************************/
-
-static BOOL account_policy_cache_timestamp(uint32 *value, BOOL update,
- const char *ap_name)
-{
- pstring key;
- uint32 val = 0;
- time_t now;
-
- if (ap_name == NULL)
- return False;
-
- slprintf(key, sizeof(key)-1, "%s/%s", ap_name, AP_LASTSET);
-
- if (!init_account_policy()) {
- return False;
- }
-
- if (!tdb_fetch_uint32(tdb, key, &val) && !update) {
- DEBUG(10,("failed to get last set timestamp of cache\n"));
- return False;
- }
-
- *value = val;
-
- DEBUG(10, ("account policy cache lastset was: %s\n", http_timestring(val)));
-
- if (update) {
-
- now = time(NULL);
-
- if (!tdb_store_uint32(tdb, key, (uint32)now)) {
- DEBUG(1, ("tdb_store_uint32 failed for %s\n", key));
- return False;
- }
- DEBUG(10, ("account policy cache lastset now: %s\n", http_timestring(now)));
- *value = now;
- }
-
- return True;
-}
-
-/*****************************************************************************
Get default value for account policy
*****************************************************************************/
@@ -262,10 +213,13 @@ BOOL init_account_policy(void)
return True;
}
- tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
- if (!tdb) {
- DEBUG(0,("Failed to open account policy database\n"));
- return False;
+ tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+ if (!tdb) { /* the account policies files does not exist or open failed, try to create a new one */
+ tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ if (!tdb) {
+ DEBUG(0,("Failed to open account policy database\n"));
+ return False;
+ }
}
/* handle a Samba upgrade */
@@ -311,7 +265,7 @@ Get an account policy (from tdb)
BOOL account_policy_get(int field, uint32 *value)
{
- fstring name;
+ const char *name;
uint32 regval;
if (!init_account_policy()) {
@@ -322,8 +276,8 @@ BOOL account_policy_get(int field, uint32 *value)
*value = 0;
}
- fstrcpy(name, decode_account_policy_name(field));
- if (!*name) {
+ name = decode_account_policy_name(field);
+ if (name == NULL) {
DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field));
return False;
}
@@ -348,14 +302,14 @@ Set an account policy (in tdb)
BOOL account_policy_set(int field, uint32 value)
{
- fstring name;
+ const char *name;
if (!init_account_policy()) {
return False;
}
- fstrcpy(name, decode_account_policy_name(field));
- if (!*name) {
+ name = decode_account_policy_name(field);
+ if (name == NULL) {
DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field));
return False;
}
@@ -376,8 +330,10 @@ Set an account policy in the cache
BOOL cache_account_policy_set(int field, uint32 value)
{
- uint32 lastset;
const char *policy_name = NULL;
+ char *cache_key = NULL;
+ char *cache_value = NULL;
+ BOOL ret = False;
policy_name = decode_account_policy_name(field);
if (policy_name == NULL) {
@@ -385,94 +341,59 @@ BOOL cache_account_policy_set(int field, uint32 value)
return False;
}
- DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
-
- if (!account_policy_set(field, value)) {
- return False;
- }
-
- if (!account_policy_cache_timestamp(&lastset, True, policy_name))
- {
- DEBUG(10,("cache_account_policy_set: failed to get lastest cache update timestamp\n"));
- return False;
- }
-
- DEBUG(10,("cache_account_policy_set: cache valid until: %s\n", http_timestring(lastset+AP_TTL)));
-
- return True;
-}
-
-/*****************************************************************************
-Check whether account policies have been migrated to passdb
-*****************************************************************************/
-
-BOOL account_policy_migrated(BOOL init)
-{
- pstring key;
- uint32 val;
- time_t now;
-
- slprintf(key, sizeof(key)-1, "AP_MIGRATED_TO_PASSDB");
-
- if (!init_account_policy()) {
- return False;
- }
-
- if (init) {
- now = time(NULL);
-
- if (!tdb_store_uint32(tdb, key, (uint32)now)) {
- DEBUG(1, ("tdb_store_uint32 failed for %s\n", key));
- return False;
- }
-
- return True;
+ if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
+ DEBUG(0, ("asprintf failed\n"));
+ goto done;
}
- if (!tdb_fetch_uint32(tdb, key, &val)) {
- return False;
+ if (asprintf(&cache_value, "%lu\n", (unsigned long)value) < 0) {
+ DEBUG(0, ("asprintf failed\n"));
+ goto done;
}
- return True;
-}
-
-/*****************************************************************************
- Remove marker that informs that account policies have been migrated to passdb
-*****************************************************************************/
+ DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
-BOOL remove_account_policy_migrated(void)
-{
- if (!init_account_policy()) {
- return False;
- }
+ ret = gencache_set(cache_key, cache_value, time(NULL)+AP_TTL);
- return tdb_delete_bystring(tdb, "AP_MIGRATED_TO_PASSDB");
+ done:
+ SAFE_FREE(cache_key);
+ SAFE_FREE(cache_value);
+ return ret;
}
-
/*****************************************************************************
Get an account policy from the cache
*****************************************************************************/
BOOL cache_account_policy_get(int field, uint32 *value)
{
- uint32 lastset;
+ const char *policy_name = NULL;
+ char *cache_key = NULL;
+ char *cache_value = NULL;
+ BOOL ret = False;
- if (!account_policy_cache_timestamp(&lastset, False,
- decode_account_policy_name(field)))
- {
- DEBUG(10,("cache_account_policy_get: failed to get latest cache update timestamp\n"));
+ policy_name = decode_account_policy_name(field);
+ if (policy_name == NULL) {
+ DEBUG(0,("cache_account_policy_set: no policy found\n"));
return False;
}
- if ((lastset + AP_TTL) < (uint32)time(NULL) ) {
- DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n"));
- return False;
- }
+ if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
+ DEBUG(0, ("asprintf failed\n"));
+ goto done;
+ }
- return account_policy_get(field, value);
-}
+ if (gencache_get(cache_key, &cache_value, NULL)) {
+ uint32 tmp = strtoul(cache_value, NULL, 10);
+ *value = tmp;
+ ret = True;
+ }
+ done:
+ SAFE_FREE(cache_key);
+ SAFE_FREE(cache_value);
+ return ret;
+}
/****************************************************************************
****************************************************************************/
diff --git a/source/lib/adt_tree.c b/source/lib/adt_tree.c
index 05a470bc49e..acd61ee4775 100644
--- a/source/lib/adt_tree.c
+++ b/source/lib/adt_tree.c
@@ -334,7 +334,7 @@ static void pathtree_print_children( TREE_NODE *node, int debug, const char *pat
void* pathtree_find( SORTED_TREE *tree, char *key )
{
- char *keystr, *base, *str, *p;
+ char *keystr, *base = NULL, *str = NULL, *p;
TREE_NODE *current;
void *result = NULL;
@@ -383,7 +383,8 @@ static void pathtree_print_children( TREE_NODE *node, int debug, const char *pat
trim_tree_keypath( p, &base, &str );
DEBUG(11,("pathtree_find: [loop] base => [%s], new_path => [%s]\n",
- base, str));
+ base ? base : "",
+ str ? str : ""));
/* iterate to the next child */
diff --git a/source/lib/afs.c b/source/lib/afs.c
index 8a304adcf0c..ea83fdebc25 100644
--- a/source/lib/afs.c
+++ b/source/lib/afs.c
@@ -211,6 +211,7 @@ char *afs_createtoken_str(const char *username, const char *cell)
BOOL afs_login(connection_struct *conn)
{
+ extern userdom_struct current_user_info;
extern struct current_user current_user;
DATA_BLOB ticket;
pstring afs_username;
@@ -222,7 +223,11 @@ BOOL afs_login(connection_struct *conn)
struct ClearToken ct;
pstrcpy(afs_username, lp_afs_username_map());
- standard_sub_conn(conn, afs_username, sizeof(afs_username));
+ standard_sub_advanced(SNUM(conn), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ afs_username, sizeof(afs_username));
user_sid = &current_user.nt_user_token->user_sids[0];
pstring_sub(afs_username, "%s", sid_string_static(user_sid));
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 097d746a638..3d02988a979 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -56,7 +56,8 @@ static const char *charset_name(charset_t ch)
{
const char *ret = NULL;
- if (ch == CH_UCS2) ret = "UTF-16LE";
+ if (ch == CH_UTF16LE) ret = "UTF-16LE";
+ else if (ch == CH_UTF16BE) ret = "UTF-16BE";
else if (ch == CH_UNIX) ret = lp_unix_charset();
else if (ch == CH_DOS) ret = lp_dos_charset();
else if (ch == CH_DISPLAY) ret = lp_display_charset();
@@ -132,11 +133,11 @@ void init_iconv(void)
/* so that charset_name() works we need to get the UNIX<->UCS2 going
first */
- if (!conv_handles[CH_UNIX][CH_UCS2])
- conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII");
+ if (!conv_handles[CH_UNIX][CH_UTF16LE])
+ conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII");
- if (!conv_handles[CH_UCS2][CH_UNIX])
- conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2));
+ if (!conv_handles[CH_UTF16LE][CH_UNIX])
+ conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE));
for (c1=0;c1<NUM_CHARSETS;c1++) {
for (c2=0;c2<NUM_CHARSETS;c2++) {
@@ -156,10 +157,10 @@ void init_iconv(void)
if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
charset_name((charset_t)c1), charset_name((charset_t)c2)));
- if (c1 != CH_UCS2) {
+ if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) {
n1 = "ASCII";
}
- if (c2 != CH_UCS2) {
+ if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) {
n2 = "ASCII";
}
DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
@@ -214,7 +215,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
descriptor = conv_handles[from][to];
if (srclen == (size_t)-1) {
- if (from == CH_UCS2) {
+ if (from == CH_UTF16LE || from == CH_UTF16BE) {
srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
} else {
srclen = strlen((const char *)src)+1;
@@ -286,8 +287,11 @@ static size_t convert_string_internal(charset_t from, charset_t to,
if (o_len == 0 || i_len == 0)
return destlen - o_len;
- if (from == CH_UCS2 && to != CH_UCS2) {
- /* Can't convert from ucs2 to multibyte. Replace with the default fail char. */
+ if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
+ ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
+ /* Can't convert from utf16 any endian to multibyte.
+ Replace with the default fail char.
+ */
if (i_len < 2)
return destlen - o_len;
if (i_len >= 2) {
@@ -306,8 +310,10 @@ static size_t convert_string_internal(charset_t from, charset_t to,
/* Keep trying with the next char... */
goto again;
- } else if (from != CH_UCS2 && to == CH_UCS2) {
- /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
+ } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
+ /* Can't convert to UTF16LE - just widen by adding the
+ default fail char then zero.
+ */
if (o_len < 2)
return destlen - o_len;
@@ -326,7 +332,8 @@ static size_t convert_string_internal(charset_t from, charset_t to,
/* Keep trying with the next char... */
goto again;
- } else if (from != CH_UCS2 && to != CH_UCS2) {
+ } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
+ to != CH_UTF16LE && to != CH_UTF16BE) {
/* Failed multibyte to multibyte. Just copy the default fail char and
try again. */
outbuf[0] = lp_failed_convert_char();
@@ -384,7 +391,7 @@ size_t convert_string(charset_t from, charset_t to,
if (srclen == 0)
return 0;
- if (from != CH_UCS2 && to != CH_UCS2) {
+ if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
const unsigned char *p = (const unsigned char *)src;
unsigned char *q = (unsigned char *)dest;
size_t slen = srclen;
@@ -419,7 +426,7 @@ size_t convert_string(charset_t from, charset_t to,
}
}
return retval;
- } else if (from == CH_UCS2 && to != CH_UCS2) {
+ } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
const unsigned char *p = (const unsigned char *)src;
unsigned char *q = (unsigned char *)dest;
size_t retval = 0;
@@ -455,7 +462,7 @@ size_t convert_string(charset_t from, charset_t to,
}
}
return retval;
- } else if (from != CH_UCS2 && to == CH_UCS2) {
+ } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
const unsigned char *p = (const unsigned char *)src;
unsigned char *q = (unsigned char *)dest;
size_t retval = 0;
@@ -516,13 +523,14 @@ size_t convert_string(charset_t from, charset_t to,
**/
size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
- void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
+ void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
{
size_t i_len, o_len, destlen = MAX(srclen, 512);
size_t retval;
const char *inbuf = (const char *)src;
char *outbuf = NULL, *ob = NULL;
smb_iconv_t descriptor;
+ void **dest = (void **)dst;
*dest = NULL;
@@ -628,8 +636,12 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
if (o_len == 0 || i_len == 0)
goto out;
- if (from == CH_UCS2 && to != CH_UCS2) {
- /* Can't convert from ucs2 to multibyte. Just use the default fail char. */
+ if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
+ ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
+ /* Can't convert from utf16 any endian to multibyte.
+ Replace with the default fail char.
+ */
+
if (i_len < 2)
goto out;
@@ -649,8 +661,10 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
/* Keep trying with the next char... */
goto again;
- } else if (from != CH_UCS2 && to == CH_UCS2) {
- /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
+ } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
+ /* Can't convert to UTF16LE - just widen by adding the
+ default fail char then zero.
+ */
if (o_len < 2)
goto out;
@@ -669,9 +683,10 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
/* Keep trying with the next char... */
goto again;
- } else if (from != CH_UCS2 && to != CH_UCS2) {
+ } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
+ to != CH_UTF16LE && to != CH_UTF16BE) {
/* Failed multibyte to multibyte. Just copy the default fail char and
- try again. */
+ try again. */
outbuf[0] = lp_failed_convert_char();
inbuf++;
@@ -702,9 +717,11 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
*
* @returns Size in bytes of the converted string; or -1 in case of error.
**/
-static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
- void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
+size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
+ void const *src, size_t srclen, void *dst,
+ BOOL allow_bad_conv)
{
+ void **dest = (void **)dst;
size_t dest_len;
*dest = NULL;
@@ -730,7 +747,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
return srclen;
}
- size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
+ size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
free(buffer);
return size;
}
@@ -766,14 +783,14 @@ char *strdup_upper(const char *s)
/* MB case. */
size_t size;
wpstring buffer;
- size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer), True);
+ size = convert_string(CH_UNIX, CH_UTF16LE, s, -1, buffer, sizeof(buffer), True);
if (size == (size_t)-1) {
return NULL;
}
strupper_w(buffer);
- size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
+ size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
if (size == (size_t)-1) {
return NULL;
}
@@ -787,7 +804,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
size_t size;
smb_ucs2_t *buffer = NULL;
- size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
+ size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
(void **)(void *)&buffer, True);
if (size == (size_t)-1 || !buffer) {
smb_panic("failed to create UCS2 buffer");
@@ -796,7 +813,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
SAFE_FREE(buffer);
return srclen;
}
- size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
+ size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
SAFE_FREE(buffer);
return size;
}
@@ -904,7 +921,7 @@ size_t push_ascii_nstring(void *dest, const char *src)
for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
unsigned char mb[10];
/* Convert one smb_ucs2_t character at a time. */
- size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
+ size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
memcpy((char *)dest + dest_len, mb, mb_len);
dest_len += mb_len;
@@ -944,9 +961,9 @@ size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len,
if (flags & STR_TERMINATE) {
if (src_len == (size_t)-1) {
- src_len = strlen(src) + 1;
+ src_len = strlen((const char *)src) + 1;
} else {
- size_t len = strnlen(src, src_len);
+ size_t len = strnlen((const char *)src, src_len);
if (len < src_len)
len++;
src_len = len;
@@ -1026,7 +1043,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_
/* ucs2 is always a multiple of 2 bytes */
dest_len &= ~1;
- ret = convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len, True);
+ ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
if (ret == (size_t)-1) {
return 0;
}
@@ -1034,9 +1051,13 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_
len += ret;
if (flags & STR_UPPER) {
- smb_ucs2_t *dest_ucs2 = dest;
+ smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
size_t i;
- for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
+
+ /* We check for i < (ret / 2) below as the dest string isn't null
+ terminated if STR_TERMINATE isn't set. */
+
+ for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
smb_ucs2_t v = toupper_w(dest_ucs2[i]);
if (v != dest_ucs2[i]) {
dest_ucs2[i] = v;
@@ -1062,7 +1083,7 @@ size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
+ return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
}
@@ -1080,7 +1101,7 @@ size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
+ return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
}
/**
@@ -1178,7 +1199,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
if (flags & STR_TERMINATE) {
/* src_len -1 is the default for null terminated strings. */
if (src_len != (size_t)-1) {
- size_t len = strnlen_w(src, src_len/2);
+ size_t len = strnlen_w((const smb_ucs2_t *)src,
+ src_len/2);
if (len < src_len/2)
len++;
src_len = len*2;
@@ -1189,7 +1211,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
if (src_len != (size_t)-1)
src_len &= ~1;
- ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len, True);
+ ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
if (ret == (size_t)-1) {
return 0;
}
@@ -1227,7 +1249,7 @@ size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
{
size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
*dest = NULL;
- return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
+ return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
}
/**
@@ -1242,7 +1264,7 @@ size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
{
size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
*dest = NULL;
- return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
+ return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
}
/**
@@ -1370,33 +1392,85 @@ size_t align_string(const void *base_ptr, const char *p, int flags)
return 0;
}
-/****************************************************************
- Calculate the size (in bytes) of the next multibyte character in
- our internal character set. Note that p must be pointing to a
- valid mb char, not within one.
-****************************************************************/
+/*
+ Return the unicode codepoint for the next multi-byte CH_UNIX character
+ in the string. The unicode codepoint (codepoint_t) is an unsinged 32 bit value.
+
+ Also return the number of bytes consumed (which tells the caller
+ how many bytes to skip to get to the next CH_UNIX character).
+
+ Return INVALID_CODEPOINT if the next character cannot be converted.
+*/
-size_t next_mb_char_size(const char *s)
+codepoint_t next_codepoint(const char *str, size_t *size)
{
- size_t i;
+ /* It cannot occupy more than 4 bytes in UTF16 format */
+ uint8_t buf[4];
+ smb_iconv_t descriptor;
+ size_t ilen_orig;
+ size_t ilen;
+ size_t olen;
+ char *outbuf;
+
+ if ((str[0] & 0x80) == 0) {
+ *size = 1;
+ return (codepoint_t)str[0];
+ }
- if (!(*s & 0x80))
- return 1; /* ascii. */
+ /* We assume that no multi-byte character can take
+ more than 5 bytes. This is OK as we only
+ support codepoints up to 1M */
- conv_silent = True;
- for ( i = 1; i <=4; i++ ) {
- smb_ucs2_t uc;
- if (convert_string(CH_UNIX, CH_UCS2, s, i, &uc, 2, False) == 2) {
-#if 0 /* JRATEST */
- DEBUG(10,("next_mb_char_size: size %u at string %s\n",
- (unsigned int)i, s));
-#endif
- conv_silent = False;
- return i;
+ ilen_orig = strnlen(str, 5);
+ ilen = ilen_orig;
+
+ lazy_initialize_conv();
+
+ descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
+ if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
+ *size = 1;
+ return INVALID_CODEPOINT;
+ }
+
+ /* This looks a little strange, but it is needed to cope
+ with codepoints above 64k which are encoded as per RFC2781. */
+ olen = 2;
+ outbuf = (char *)buf;
+ smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
+ if (olen == 2) {
+ /* We failed to convert to a 2 byte character.
+ See if we can convert to a 4 UTF16-LE byte char encoding.
+ */
+ olen = 4;
+ outbuf = (char *)buf;
+ smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
+ if (olen == 4) {
+ /* We didn't convert any bytes */
+ *size = 1;
+ return INVALID_CODEPOINT;
}
+ olen = 4 - olen;
+ } else {
+ olen = 2 - olen;
}
- /* We're hosed - we don't know how big this is... */
- DEBUG(10,("next_mb_char_size: unknown size at string %s\n", s));
- conv_silent = False;
- return 1;
+
+ *size = ilen_orig - ilen;
+
+ if (olen == 2) {
+ /* 2 byte, UTF16-LE encoded value. */
+ return (codepoint_t)SVAL(buf, 0);
+ }
+ if (olen == 4) {
+ /* Decode a 4 byte UTF16-LE character manually.
+ See RFC2871 for the encoding machanism.
+ */
+ codepoint_t w1 = SVAL(buf,0) & ~0xD800;
+ codepoint_t w2 = SVAL(buf,2) & ~0xDC00;
+
+ return (codepoint_t)0x10000 +
+ (w1 << 10) + w2;
+ }
+
+ /* no other length is valid */
+ return INVALID_CODEPOINT;
}
diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c
index ccd0d27f47b..c7eadc1acfb 100644
--- a/source/lib/data_blob.c
+++ b/source/lib/data_blob.c
@@ -47,9 +47,9 @@ DATA_BLOB data_blob(const void *p, size_t length)
}
if (p) {
- ret.data = smb_xmemdup(p, length);
+ ret.data = (uint8 *)smb_xmemdup(p, length);
} else {
- ret.data = SMB_XMALLOC_ARRAY(unsigned char, length);
+ ret.data = SMB_XMALLOC_ARRAY(uint8, length);
}
ret.length = length;
ret.free = free_data_blob;
@@ -70,11 +70,11 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
}
if (p) {
- ret.data = TALLOC_MEMDUP(mem_ctx, p, length);
+ ret.data = (uint8 *)TALLOC_MEMDUP(mem_ctx, p, length);
if (ret.data == NULL)
smb_panic("data_blob_talloc: talloc_memdup failed.\n");
} else {
- ret.data = TALLOC(mem_ctx, length);
+ ret.data = (uint8 *)TALLOC(mem_ctx, length);
if (ret.data == NULL)
smb_panic("data_blob_talloc: talloc failed.\n");
}
@@ -102,7 +102,7 @@ void data_blob_free(DATA_BLOB *d)
Clear a DATA_BLOB's contents
*******************************************************************/
-static void data_blob_clear(DATA_BLOB *d)
+void data_blob_clear(DATA_BLOB *d)
{
if (d->data) {
memset(d->data, 0, d->length);
@@ -118,3 +118,28 @@ void data_blob_clear_free(DATA_BLOB *d)
data_blob_clear(d);
data_blob_free(d);
}
+
+/**
+ useful for constructing data blobs in test suites, while
+ avoiding const warnings
+**/
+DATA_BLOB data_blob_string_const(const char *str)
+{
+ DATA_BLOB blob;
+ blob.data = CONST_DISCARD(uint8 *, str);
+ blob.length = strlen(str);
+ blob.free = NULL;
+ return blob;
+}
+
+/**
+ * Create a new data blob from const data
+ */
+DATA_BLOB data_blob_const(const void *p, size_t length)
+{
+ DATA_BLOB blob;
+ blob.data = CONST_DISCARD(uint8 *, p);
+ blob.length = length;
+ blob.free = NULL;
+ return blob;
+}
diff --git a/source/lib/debug.c b/source/lib/debug.c
index 2b6c42b8eb0..5f141661106 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -236,7 +236,7 @@ static char *debug_list_class_names_and_levels(void)
}
/* create single string list - add space for newline */
- b = buf = SMB_MALLOC(dim+1);
+ b = buf = (char *)SMB_MALLOC(dim+1);
if (!buf) {
err = True;
goto done;
@@ -320,7 +320,7 @@ int debug_add_class(const char *classname)
new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1);
if (!new_ptr)
return -1;
- DEBUGLEVEL_CLASS = new_ptr;
+ DEBUGLEVEL_CLASS = (int *)new_ptr;
DEBUGLEVEL_CLASS[ndx] = 0;
/* debug_level is the pointer used for the DEBUGLEVEL-thingy */
@@ -337,13 +337,13 @@ int debug_add_class(const char *classname)
new_ptr = SMB_REALLOC_ARRAY(new_ptr, BOOL, debug_num_classes + 1);
if (!new_ptr)
return -1;
- DEBUGLEVEL_CLASS_ISSET = new_ptr;
+ DEBUGLEVEL_CLASS_ISSET = (int *)new_ptr;
DEBUGLEVEL_CLASS_ISSET[ndx] = False;
new_ptr = SMB_REALLOC_ARRAY(classname_table, char *, debug_num_classes + 1);
if (!new_ptr)
return -1;
- classname_table = new_ptr;
+ classname_table = (char **)new_ptr;
classname_table[ndx] = SMB_STRDUP(classname);
if (! classname_table[ndx])
@@ -472,9 +472,9 @@ BOOL debug_parse_levels(const char *params_str)
****************************************************************************/
static void debug_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
- const char *params_str = buf;
+ const char *params_str = (const char *)buf;
/* Check, it's a proper string! */
if (params_str[len-1] != '\0') {
@@ -509,7 +509,7 @@ void debug_message_send(pid_t pid, const char *params_str)
****************************************************************************/
static void debuglevel_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
char *message = debug_list_class_names_and_levels();
@@ -539,8 +539,8 @@ void debug_init(void)
initialised = True;
- message_register(MSG_DEBUG, debug_message);
- message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message);
+ message_register(MSG_DEBUG, debug_message, NULL);
+ message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message, NULL);
for(p = default_classname_table; *p; p++) {
debug_add_class(*p);
@@ -981,7 +981,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
/* Print it all out at once to prevent split syslog output. */
(void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
- timestring(lp_debug_hires_timestamp()), level,
+ current_timestring(lp_debug_hires_timestamp()), level,
header_str, file, func, line );
}
diff --git a/source/lib/display_sec.c b/source/lib/display_sec.c
index 49a86c261ca..2b3542922c1 100644
--- a/source/lib/display_sec.c
+++ b/source/lib/display_sec.c
@@ -63,7 +63,7 @@ char *get_sec_mask_str(uint32 type)
****************************************************************************/
void display_sec_access(SEC_ACCESS *info)
{
- printf("\t\tPermissions: 0x%x: %s\n", info->mask, get_sec_mask_str(info->mask));
+ printf("\t\tPermissions: 0x%x: %s\n", *info, get_sec_mask_str(*info));
}
/****************************************************************************
@@ -92,7 +92,7 @@ void display_sec_ace(SEC_ACE *ace)
break;
}
printf(" (%d) flags: %d\n", ace->type, ace->flags);
- display_sec_access(&ace->info);
+ display_sec_access(&ace->access_mask);
sid_to_string(sid_str, &ace->trustee);
printf("\t\tSID: %s\n\n", sid_str);
}
@@ -110,7 +110,7 @@ void display_sec_acl(SEC_ACL *sec_acl)
if (sec_acl->size != 0 && sec_acl->num_aces != 0)
for (i = 0; i < sec_acl->num_aces; i++)
- display_sec_ace(&sec_acl->ace[i]);
+ display_sec_ace(&sec_acl->aces[i]);
}
@@ -179,8 +179,8 @@ void display_sec_desc(SEC_DESC *sec)
printf("\tOwner SID:\t%s\n", sid_str);
}
- if (sec->grp_sid) {
- sid_to_string(sid_str, sec->grp_sid);
+ if (sec->group_sid) {
+ sid_to_string(sid_str, sec->group_sid);
printf("\tParent SID:\t%s\n", sid_str);
}
}
diff --git a/source/lib/dmallocmsg.c b/source/lib/dmallocmsg.c
index 1b2308ecba6..fed7bf59c52 100644
--- a/source/lib/dmallocmsg.c
+++ b/source/lib/dmallocmsg.c
@@ -35,8 +35,10 @@ static unsigned long our_dm_mark = 0;
* Respond to a POOL_USAGE message by sending back string form of memory
* usage stats.
**/
-static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED(src_pid),
- void *UNUSED(buf), size_t UNUSED(len))
+static void msg_req_dmalloc_mark(int UNUSED(msg_type),
+ struct process_id UNUSED(src_pid),
+ void *UNUSED(buf), size_t UNUSED(len),
+ void *private_data)
{
#ifdef ENABLE_DMALLOC
our_dm_mark = dmalloc_mark();
@@ -50,7 +52,8 @@ static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED(
static void msg_req_dmalloc_log_changed(int UNUSED(msg_type),
struct process_id UNUSED(src_pid),
- void *UNUSED(buf), size_t UNUSED(len))
+ void *UNUSED(buf), size_t UNUSED(len),
+ void *private_data)
{
#ifdef ENABLE_DMALLOC
dmalloc_log_changed(our_dm_mark, True, True, True);
@@ -66,7 +69,8 @@ static void msg_req_dmalloc_log_changed(int UNUSED(msg_type),
**/
void register_dmalloc_msgs(void)
{
- message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark);
- message_register(MSG_REQ_DMALLOC_LOG_CHANGED, msg_req_dmalloc_log_changed);
+ message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark, NULL);
+ message_register(MSG_REQ_DMALLOC_LOG_CHANGED,
+ msg_req_dmalloc_log_changed, NULL);
DEBUG(2, ("Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED\n"));
}
diff --git a/source/lib/dprintf.c b/source/lib/dprintf.c
index 8ed2fa5d8cd..2312c3db0cb 100644
--- a/source/lib/dprintf.c
+++ b/source/lib/dprintf.c
@@ -54,7 +54,7 @@
charset, but beware of it growing */
maxlen = ret*2;
again:
- p2 = SMB_MALLOC(maxlen);
+ p2 = (char *)SMB_MALLOC(maxlen);
if (!p2) {
SAFE_FREE(p);
return -1;
diff --git a/source/lib/dummysmbd.c b/source/lib/dummysmbd.c
index 9b587224e3e..a291a5884d9 100644
--- a/source/lib/dummysmbd.c
+++ b/source/lib/dummysmbd.c
@@ -24,11 +24,6 @@
#include "includes.h"
-void decrement_smbd_process_count( void )
-{
- return;
-}
-
int find_service(fstring service)
{
return -1;
@@ -38,3 +33,18 @@ BOOL conn_snum_used(int snum)
{
return False;
}
+
+void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
+{
+}
+
+void send_stat_cache_delete_message(const char *name)
+{
+}
+
+NTSTATUS can_delete_directory(struct connection_struct *conn,
+ const char *dirname)
+{
+ return NT_STATUS_OK;
+}
+
diff --git a/source/lib/events.c b/source/lib/events.c
index 242c198511e..a00db77b6be 100644
--- a/source/lib/events.c
+++ b/source/lib/events.c
@@ -21,32 +21,93 @@
#include "includes.h"
-static struct timed_event *timed_events;
+struct timed_event {
+ struct timed_event *next, *prev;
+ struct event_context *event_ctx;
+ struct timeval when;
+ const char *event_name;
+ void (*handler)(struct event_context *event_ctx,
+ struct timed_event *te,
+ const struct timeval *now,
+ void *private_data);
+ void *private_data;
+};
-static int timed_event_destructor(void *p)
+struct fd_event {
+ struct fd_event *prev, *next;
+ struct event_context *event_ctx;
+ int fd;
+ uint16_t flags; /* see EVENT_FD_* flags */
+ void (*handler)(struct event_context *event_ctx,
+ struct fd_event *event,
+ uint16 flags,
+ void *private_data);
+ void *private_data;
+};
+
+#define EVENT_FD_WRITEABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
+#define EVENT_FD_READABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ)
+
+#define EVENT_FD_NOT_WRITEABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE)
+#define EVENT_FD_NOT_READABLE(fde) \
+ event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ)
+
+struct event_context {
+ struct timed_event *timed_events;
+ struct fd_event *fd_events;
+};
+
+static int timed_event_destructor(struct timed_event *te)
{
- struct timed_event *te = talloc_get_type_abort(p, struct timed_event);
DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
te->event_name));
- DLIST_REMOVE(timed_events, te);
+ DLIST_REMOVE(te->event_ctx->timed_events, te);
return 0;
}
/****************************************************************************
+ Add te by time.
+****************************************************************************/
+
+static void add_event_by_time(struct timed_event *te)
+{
+ struct event_context *ctx = te->event_ctx;
+ struct timed_event *last_te, *cur_te;
+
+ /* Keep the list ordered by time. We must preserve this. */
+ last_te = NULL;
+ for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) {
+ /* if the new event comes before the current one break */
+ if (!timeval_is_zero(&cur_te->when) &&
+ timeval_compare(&te->when, &cur_te->when) < 0) {
+ break;
+ }
+ last_te = cur_te;
+ }
+
+ DLIST_ADD_AFTER(ctx->timed_events, te, last_te);
+}
+
+/****************************************************************************
Schedule a function for future calling, cancel with TALLOC_FREE().
It's the responsibility of the handler to call TALLOC_FREE() on the event
handed to it.
****************************************************************************/
-struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
+struct timed_event *event_add_timed(struct event_context *event_ctx,
+ TALLOC_CTX *mem_ctx,
struct timeval when,
const char *event_name,
- void (*handler)(struct timed_event *te,
+ void (*handler)(struct event_context *event_ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data),
void *private_data)
{
- struct timed_event *te, *last_te, *cur_te;
+ struct timed_event *te;
te = TALLOC_P(mem_ctx, struct timed_event);
if (te == NULL) {
@@ -54,23 +115,14 @@ struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
return NULL;
}
+ te->event_ctx = event_ctx;
te->when = when;
te->event_name = event_name;
te->handler = handler;
te->private_data = private_data;
- /* keep the list ordered */
- last_te = NULL;
- for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
- /* if the new event comes before the current one break */
- if (!timeval_is_zero(&cur_te->when) &&
- timeval_compare(&te->when, &cur_te->when) < 0) {
- break;
- }
- last_te = cur_te;
- }
+ add_event_by_time(te);
- DLIST_ADD_AFTER(timed_events, te, last_te);
talloc_set_destructor(te, timed_event_destructor);
DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
@@ -78,44 +130,206 @@ struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
return te;
}
-void run_events(void)
+static int fd_event_destructor(struct fd_event *fde)
{
- struct timeval now;
+ struct event_context *event_ctx = fde->event_ctx;
- if (timed_events == NULL) {
- /* No syscall if there are no events */
- DEBUG(11, ("run_events: No events\n"));
- return;
+ DLIST_REMOVE(event_ctx->fd_events, fde);
+ return 0;
+}
+
+struct fd_event *event_add_fd(struct event_context *event_ctx,
+ TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags,
+ void (*handler)(struct event_context *event_ctx,
+ struct fd_event *event,
+ uint16 flags,
+ void *private_data),
+ void *private_data)
+{
+ struct fd_event *fde;
+
+ if (!(fde = TALLOC_P(mem_ctx, struct fd_event))) {
+ return NULL;
}
- GetTimeOfDay(&now);
+ fde->event_ctx = event_ctx;
+ fde->fd = fd;
+ fde->flags = flags;
+ fde->handler = handler;
+ fde->private_data = private_data;
+
+ DLIST_ADD(event_ctx->fd_events, fde);
- if (timeval_compare(&now, &timed_events->when) < 0) {
- /* Nothing to do yet */
- DEBUG(11, ("run_events: Nothing to do\n"));
+ talloc_set_destructor(fde, fd_event_destructor);
+ return fde;
+}
+
+void event_fd_set_writeable(struct fd_event *fde)
+{
+ fde->flags |= EVENT_FD_WRITE;
+}
+
+void event_fd_set_not_writeable(struct fd_event *fde)
+{
+ fde->flags &= ~EVENT_FD_WRITE;
+}
+
+void event_fd_set_readable(struct fd_event *fde)
+{
+ fde->flags |= EVENT_FD_READ;
+}
+
+void event_fd_set_not_readable(struct fd_event *fde)
+{
+ fde->flags &= ~EVENT_FD_READ;
+}
+
+void event_add_to_select_args(struct event_context *event_ctx,
+ const struct timeval *now,
+ fd_set *read_fds, fd_set *write_fds,
+ struct timeval *timeout, int *maxfd)
+{
+ struct fd_event *fde;
+ struct timeval diff;
+
+ for (fde = event_ctx->fd_events; fde; fde = fde->next) {
+ if (fde->flags & EVENT_FD_READ) {
+ FD_SET(fde->fd, read_fds);
+ }
+ if (fde->flags & EVENT_FD_WRITE) {
+ FD_SET(fde->fd, write_fds);
+ }
+
+ if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE))
+ && (fde->fd > *maxfd)) {
+ *maxfd = fde->fd;
+ }
+ }
+
+ if (event_ctx->timed_events == NULL) {
return;
}
- DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
- (unsigned long)timed_events));
+ diff = timeval_until(now, &event_ctx->timed_events->when);
+ *timeout = timeval_min(timeout, &diff);
+}
+
+BOOL run_events(struct event_context *event_ctx,
+ int selrtn, fd_set *read_fds, fd_set *write_fds)
+{
+ BOOL fired = False;
+ struct fd_event *fde, *next;
+
+ /* Run all events that are pending, not just one (as we
+ did previously. */
+
+ while (event_ctx->timed_events) {
+ struct timeval now;
+ GetTimeOfDay(&now);
+
+ if (timeval_compare(
+ &now, &event_ctx->timed_events->when) < 0) {
+ /* Nothing to do yet */
+ DEBUG(11, ("run_events: Nothing to do\n"));
+ break;
+ }
+
+ DEBUG(10, ("Running event \"%s\" %lx\n",
+ event_ctx->timed_events->event_name,
+ (unsigned long)event_ctx->timed_events));
+
+ event_ctx->timed_events->handler(
+ event_ctx,
+ event_ctx->timed_events, &now,
+ event_ctx->timed_events->private_data);
+
+ fired = True;
+ }
+
+ if (fired) {
+ /*
+ * We might have changed the socket status during the timed
+ * events, return to run select again.
+ */
+ return True;
+ }
+
+ if (selrtn == 0) {
+ /*
+ * No fd ready
+ */
+ return fired;
+ }
- timed_events->handler(timed_events, &now, timed_events->private_data);
- return;
+ for (fde = event_ctx->fd_events; fde; fde = next) {
+ uint16 flags = 0;
+
+ next = fde->next;
+ if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ;
+ if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE;
+
+ if (flags) {
+ fde->handler(event_ctx, fde, flags, fde->private_data);
+ fired = True;
+ }
+ }
+
+ return fired;
}
-struct timeval *get_timed_events_timeout(struct timeval *to_ret)
+
+struct timeval *get_timed_events_timeout(struct event_context *event_ctx,
+ struct timeval *to_ret)
{
struct timeval now;
- if (timed_events == NULL) {
+ if (event_ctx->timed_events == NULL) {
return NULL;
}
now = timeval_current();
- *to_ret = timeval_until(&now, &timed_events->when);
+ *to_ret = timeval_until(&now, &event_ctx->timed_events->when);
DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
(int)to_ret->tv_usec));
return to_ret;
}
+
+struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
+{
+ return TALLOC_ZERO_P(NULL, struct event_context);
+}
+
+int set_event_dispatch_time(struct event_context *event_ctx,
+ const char *event_name, struct timeval when)
+{
+ struct timed_event *te;
+
+ for (te = event_ctx->timed_events; te; te = te->next) {
+ if (strcmp(event_name, te->event_name) == 0) {
+ DLIST_REMOVE(event_ctx->timed_events, te);
+ te->when = when;
+ add_event_by_time(te);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Returns 1 if event was found and cancelled, 0 otherwise. */
+
+int cancel_named_event(struct event_context *event_ctx,
+ const char *event_name)
+{
+ struct timed_event *te;
+
+ for (te = event_ctx->timed_events; te; te = te->next) {
+ if (strcmp(event_name, te->event_name) == 0) {
+ TALLOC_FREE(te);
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/source/lib/fault.c b/source/lib/fault.c
index dc8c276d02c..b632a5c82fa 100644
--- a/source/lib/fault.c
+++ b/source/lib/fault.c
@@ -160,12 +160,13 @@ void dump_core_setup(const char *progname)
exit(1);
}
+#if DUMP_CORE
if (*corepath != '\0') {
/* The chdir might fail if we dump core before we finish
* processing the config file.
*/
if (chdir(corepath) != 0) {
- DEBUG(0, ("unable to change to %s", corepath));
+ DEBUG(0, ("unable to change to %s\n", corepath));
DEBUGADD(0, ("refusing to dump core\n"));
exit(1);
}
@@ -182,5 +183,9 @@ void dump_core_setup(const char *progname)
#endif
abort();
+
+#else /* DUMP_CORE */
+ exit(1);
+#endif /* DUMP_CORE */
}
diff --git a/source/lib/gencache.c b/source/lib/gencache.c
index 013eed8a00d..c58642553c0 100644
--- a/source/lib/gencache.c
+++ b/source/lib/gencache.c
@@ -130,9 +130,9 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout)
if (!valstr)
return False;
- keybuf.dptr = SMB_STRDUP(keystr);
+ keybuf.dptr = CONST_DISCARD(char *, keystr);
keybuf.dsize = strlen(keystr)+1;
- databuf.dptr = SMB_STRDUP(valstr);
+ databuf.dptr = valstr;
databuf.dsize = strlen(valstr)+1;
DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
" %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout),
@@ -141,71 +141,9 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout)
ret = tdb_store(cache, keybuf, databuf, 0);
SAFE_FREE(valstr);
- SAFE_FREE(keybuf.dptr);
- SAFE_FREE(databuf.dptr);
-
- return ret == 0;
-}
-
-
-/**
- * Set existing entry to the cache file.
- *
- * @param keystr string that represents a key of this entry
- * @param valstr text representation value being cached
- * @param timeout time when the value is expired
- *
- * @retval true when entry is successfuly set
- * @retval false on failure
- **/
-
-BOOL gencache_set_only(const char *keystr, const char *valstr, time_t timeout)
-{
- int ret = -1;
- TDB_DATA keybuf, databuf;
- char *old_valstr, *datastr;
- time_t old_timeout;
-
- /* fail completely if get null pointers passed */
- SMB_ASSERT(keystr && valstr);
-
- if (!gencache_init()) return False;
-
- if (cache_readonly) {
- return False;
- }
-
- /*
- * Check whether entry exists in the cache
- * Don't verify gencache_get exit code, since the entry may be expired
- */
- gencache_get(keystr, &old_valstr, &old_timeout);
-
- if (!(old_valstr && old_timeout)) return False;
-
- DEBUG(10, ("Setting cache entry with key = %s; old value = %s and old timeout \
- = %s\n", keystr, old_valstr, ctime(&old_timeout)));
-
- asprintf(&datastr, CACHE_DATA_FMT, (int)timeout, valstr);
- keybuf.dptr = SMB_STRDUP(keystr);
- keybuf.dsize = strlen(keystr)+1;
- databuf.dptr = SMB_STRDUP(datastr);
- databuf.dsize = strlen(datastr)+1;
- DEBUGADD(10, ("New value = %s, new timeout = %s (%d seconds %s)", valstr,
- ctime(&timeout), (int)(timeout - time(NULL)),
- timeout > time(NULL) ? "ahead" : "in the past"));
-
-
- ret = tdb_store(cache, keybuf, databuf, TDB_REPLACE);
-
- SAFE_FREE(datastr);
- SAFE_FREE(old_valstr);
- SAFE_FREE(keybuf.dptr);
- SAFE_FREE(databuf.dptr);
return ret == 0;
}
-
/**
* Delete one entry from the cache file.
@@ -230,12 +168,11 @@ BOOL gencache_del(const char *keystr)
return False;
}
- keybuf.dptr = SMB_STRDUP(keystr);
+ keybuf.dptr = CONST_DISCARD(char *, keystr);
keybuf.dsize = strlen(keystr)+1;
DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr));
ret = tdb_delete(cache, keybuf);
- SAFE_FREE(keybuf.dptr);
return ret == 0;
}
@@ -256,6 +193,8 @@ BOOL gencache_del(const char *keystr)
BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
{
TDB_DATA keybuf, databuf;
+ time_t t;
+ char *endptr;
/* fail completely if get null pointers passed */
SMB_ASSERT(keystr);
@@ -264,71 +203,55 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
return False;
}
- keybuf.dptr = SMB_STRDUP(keystr);
+ keybuf.dptr = CONST_DISCARD(char *, keystr);
keybuf.dsize = strlen(keystr)+1;
databuf = tdb_fetch(cache, keybuf);
- SAFE_FREE(keybuf.dptr);
-
- if (databuf.dptr && databuf.dsize > TIMEOUT_LEN) {
- char* entry_buf = SMB_STRNDUP(databuf.dptr, databuf.dsize);
- char *v;
- time_t t;
- unsigned u;
- int status;
- char *fmt;
- v = SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN);
- if (!v) {
- return False;
- }
+ if (databuf.dptr == NULL) {
+ DEBUG(10, ("Cache entry with key = %s couldn't be found\n",
+ keystr));
+ return False;
+ }
- SAFE_FREE(databuf.dptr);
+ t = strtol(databuf.dptr, &endptr, 10);
- asprintf(&fmt, READ_CACHE_DATA_FMT_TEMPLATE, (unsigned int)databuf.dsize - TIMEOUT_LEN);
- if (!fmt) {
- SAFE_FREE(v);
- return False;
- }
+ if ((endptr == NULL) || (*endptr != '/')) {
+ DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr));
+ SAFE_FREE(databuf.dptr);
+ return False;
+ }
- status = sscanf(entry_buf, fmt, &u, v);
- SAFE_FREE(fmt);
+ DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
+ "timeout = %s", t > time(NULL) ? "valid" :
+ "expired", keystr, endptr+1, ctime(&t)));
- if ( status != 2 ) {
- DEBUG(0, ("gencache_get: Invalid return %d from sscanf\n", status ));
- }
- t = u;
- SAFE_FREE(entry_buf);
+ if (t <= time(NULL)) {
- DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
- "timeout = %s", t > time(NULL) ? "valid" :
- "expired", keystr, v, ctime(&t)));
+ /* We're expired, delete the entry */
+ tdb_delete(cache, keybuf);
- if (valstr) {
- *valstr = v;
- } else {
- SAFE_FREE(v);
- }
+ SAFE_FREE(databuf.dptr);
+ return False;
+ }
- if (timeout) {
- *timeout = t;
+ if (valstr) {
+ *valstr = SMB_STRDUP(endptr+1);
+ if (*valstr == NULL) {
+ SAFE_FREE(databuf.dptr);
+ DEBUG(0, ("strdup failed\n"));
+ return False;
}
-
- return t > time(NULL);
-
- }
-
+ }
+
SAFE_FREE(databuf.dptr);
- if (valstr) {
- *valstr = NULL;
- }
if (timeout) {
- timeout = NULL;
+ *timeout = t;
}
- DEBUG(10, ("Cache entry with key = %s couldn't be found\n", keystr));
- return False;
-}
+ return True;
+}
+
/**
* Iterate through all entries which key matches to specified pattern
@@ -389,7 +312,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
SAFE_FREE(databuf.dptr);
- valstr = SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN);
+ valstr = (char *)SMB_MALLOC(databuf.dsize + 1 - TIMEOUT_LEN);
if (!valstr) {
SAFE_FREE(entry);
SAFE_FREE(keystr);
diff --git a/source/lib/getsmbpass.c b/source/lib/getsmbpass.c
deleted file mode 100644
index bebddc69eb4..00000000000
--- a/source/lib/getsmbpass.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright (C) 1992-1998 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library 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
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-/* Modified to use with samba by Jeremy Allison, 8th July 1995. */
-
-#include "includes.h"
-
-#ifdef REPLACE_GETPASS
-
-#ifdef SYSV_TERMIO
-
-/* SYSTEM V TERMIO HANDLING */
-
-static struct termio t;
-
-#define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
-#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
-#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
-
-#ifndef TCSAFLUSH
-#define TCSAFLUSH 1
-#endif
-
-#ifndef TCSANOW
-#define TCSANOW 0
-#endif
-
-static int tcgetattr(int fd, struct termio *t)
-{
- return ioctl(fd, TCGETA, t);
-}
-
-static int tcsetattr(int fd, int flags, struct termio *t)
-{
- if(flags & TCSAFLUSH)
- ioctl(fd, TCFLSH, TCIOFLUSH);
- return ioctl(fd, TCSETS, t);
-}
-
-#elif !defined(TCSAFLUSH)
-
-/* BSD TERMIO HANDLING */
-
-static struct sgttyb t;
-
-#define ECHO_IS_ON(t) ((t).sg_flags & ECHO)
-#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO)
-#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO)
-
-#define TCSAFLUSH 1
-#define TCSANOW 0
-
-static int tcgetattr(int fd, struct sgttyb *t)
-{
- return ioctl(fd, TIOCGETP, (char *)t);
-}
-
-static int tcsetattr(int fd, int flags, struct sgttyb *t)
-{
- return ioctl(fd, TIOCSETP, (char *)t);
-}
-
-#else /* POSIX TERMIO HANDLING */
-#define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
-#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
-#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
-
-static struct termios t;
-#endif /* SYSV_TERMIO */
-
-static SIG_ATOMIC_T gotintr;
-static int in_fd = -1;
-
-/***************************************************************
- Signal function to tell us were ^C'ed.
-****************************************************************/
-
-static void gotintr_sig(void)
-{
- gotintr = 1;
- if (in_fd != -1)
- close(in_fd); /* Safe way to force a return. */
- in_fd = -1;
-}
-
-char *getsmbpass(const char *prompt)
-{
- FILE *in, *out;
- int echo_off;
- static char buf[256];
- static size_t bufsize = sizeof(buf);
- size_t nread;
-
- /* Catch problematic signals */
- CatchSignal(SIGINT, SIGNAL_CAST gotintr_sig);
-
- /* Try to write to and read from the terminal if we can.
- If we can't open the terminal, use stderr and stdin. */
-
- in = fopen ("/dev/tty", "w+");
- if (in == NULL) {
- in = stdin;
- out = stderr;
- } else {
- out = in;
- }
-
- setvbuf(in, NULL, _IONBF, 0);
-
- /* Turn echoing off if it is on now. */
-
- if (tcgetattr (fileno (in), &t) == 0) {
- if (ECHO_IS_ON(t)) {
- TURN_ECHO_OFF(t);
- echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0;
- TURN_ECHO_ON(t);
- } else {
- echo_off = 0;
- }
- } else {
- echo_off = 0;
- }
-
- /* Write the prompt. */
- fputs(prompt, out);
- fflush(out);
-
- /* Read the password. */
- buf[0] = 0;
- if (!gotintr) {
- in_fd = fileno(in);
- fgets(buf, bufsize, in);
- }
- nread = strlen(buf);
- if (nread) {
- if (buf[nread - 1] == '\n')
- buf[nread - 1] = '\0';
- }
-
- /* Restore echoing. */
- if (echo_off) {
- if (gotintr && in_fd == -1)
- in = fopen ("/dev/tty", "w+");
- if (in != NULL)
- tcsetattr (fileno (in), TCSANOW, &t);
- }
-
- fprintf(out, "\n");
- fflush(out);
-
- if (in && in != stdin) /* We opened the terminal; now close it. */
- fclose(in);
-
- /* Catch problematic signals */
- CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL);
-
- if (gotintr) {
- printf("Interupted by signal.\n");
- fflush(stdout);
- exit(1);
- }
- return buf;
-}
-
-#else
- void getsmbpasswd_dummy(void);
- void getsmbpasswd_dummy(void) {;}
-#endif
diff --git a/source/lib/iconv.c b/source/lib/iconv.c
index c96243633fb..6e040b77f17 100644
--- a/source/lib/iconv.c
+++ b/source/lib/iconv.c
@@ -128,6 +128,7 @@ static void lazy_initialize_iconv(void)
}
}
+#ifdef HAVE_NATIVE_ICONV
/* if there was an error then reset the internal state,
this ensures that we don't have a shift state remaining for
character sets like SJIS */
@@ -135,7 +136,6 @@ static size_t sys_iconv(void *cd,
const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
-#ifdef HAVE_NATIVE_ICONV
size_t ret = iconv((iconv_t)cd,
(char **)inbuf, inbytesleft,
outbuf, outbytesleft);
@@ -145,11 +145,8 @@ static size_t sys_iconv(void *cd,
errno = saved_errno;
}
return ret;
-#else
- errno = EINVAL;
- return -1;
-#endif
}
+#endif
/**
* This is a simple portable iconv() implementaion.
diff --git a/source/lib/interface.c b/source/lib/interface.c
index 2bd7d6ddbe0..9d0b966390f 100644
--- a/source/lib/interface.c
+++ b/source/lib/interface.c
@@ -187,7 +187,11 @@ void load_interfaces(void)
total_probed = get_interfaces(ifaces, MAX_INTERFACES);
if (total_probed > 0) {
- probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
+ probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed);
+ if (!probed_ifaces) {
+ DEBUG(0,("ERROR: memdup failed\n"));
+ exit(1);
+ }
}
/* if we don't have a interfaces line then use all broadcast capable
diff --git a/source/lib/interfaces.c b/source/lib/interfaces.c
index dc30bdce47a..839cab1286c 100644
--- a/source/lib/interfaces.c
+++ b/source/lib/interfaces.c
@@ -30,27 +30,21 @@
*/
+#ifndef AUTOCONF_TEST
+#include "config.h"
+#endif
+
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/time.h>
-#include <net/if.h>
-
-#ifdef AUTOCONF_TEST
-struct iface_struct {
- char name[16];
- struct in_addr ip;
- struct in_addr netmask;
-};
-#else
-#include "config.h"
-#include "interfaces.h"
-#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -82,6 +76,12 @@ struct iface_struct {
#define QSORT_CAST (int (*)(const void *, const void *))
#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#include "interfaces.h"
+
#if HAVE_IFACE_IFCONF
/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
@@ -154,7 +154,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
return total;
}
-#elif HAVE_IFACE_IFREQ
+#define _FOUND_IFACE_ANY
+#endif /* HAVE_IFACE_IFCONF */
+#ifdef HAVE_IFACE_IFREQ
#ifndef I_STR
#include <sys/stropts.h>
@@ -249,7 +251,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
return total;
}
-#elif HAVE_IFACE_AIX
+#define _FOUND_IFACE_ANY
+#endif /* HAVE_IFACE_IFREQ */
+#ifdef HAVE_IFACE_AIX
/****************************************************************************
this one is for AIX (tested on 4.2)
@@ -284,7 +288,7 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
i = ifc.ifc_len;
while (i > 0 && total < max_interfaces) {
- unsigned inc;
+ uint_t inc;
inc = ifr->ifr_addr.sa_len;
@@ -337,7 +341,9 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
return total;
}
-#else /* a dummy version */
+#define _FOUND_IFACE_ANY
+#endif /* HAVE_IFACE_AIX */
+#ifndef _FOUND_IFACE_ANY
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
return -1;
@@ -356,10 +362,9 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
return r;
}
+int get_interfaces(struct iface_struct *ifaces, int max_interfaces);
/* this wrapper is used to remove duplicates from the interface list generated
above */
-int get_interfaces(struct iface_struct *ifaces, int max_interfaces);
-
int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
{
int total, i, j;
@@ -388,8 +393,6 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
#ifdef AUTOCONF_TEST
/* this is the autoconf driver to test get_interfaces() */
-#define MAX_INTERFACES 128
-
int main()
{
struct iface_struct ifaces[MAX_INTERFACES];
diff --git a/source/lib/ldap_escape.c b/source/lib/ldap_escape.c
index fcb787e9e85..26230884341 100644
--- a/source/lib/ldap_escape.c
+++ b/source/lib/ldap_escape.c
@@ -36,7 +36,7 @@
char *escape_ldap_string_alloc(const char *s)
{
size_t len = strlen(s)+1;
- char *output = SMB_MALLOC(len);
+ char *output = (char *)SMB_MALLOC(len);
const char *sub;
int i = 0;
char *p = output;
@@ -68,7 +68,7 @@ char *escape_ldap_string_alloc(const char *s)
if (sub) {
len = len + 3;
- output = SMB_REALLOC(output, len);
+ output = (char *)SMB_REALLOC(output, len);
if (!output) {
return NULL;
}
diff --git a/source/lib/messages.c b/source/lib/messages.c
index dd6d4137d7b..e0bf86a46ce 100644
--- a/source/lib/messages.c
+++ b/source/lib/messages.c
@@ -66,14 +66,16 @@ struct message_rec {
static struct dispatch_fns {
struct dispatch_fns *next, *prev;
int msg_type;
- void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len);
+ void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len,
+ void *private_data);
+ void *private_data;
} *dispatch_fns;
/****************************************************************************
Free global objects.
****************************************************************************/
-void gfree_messsges(void)
+void gfree_messages(void)
{
struct dispatch_fns *dfn, *next;
@@ -102,9 +104,9 @@ static void sig_usr1(void)
****************************************************************************/
static void ping_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
- const char *msg = buf ? buf : "none";
+ const char *msg = buf ? (const char *)buf : "none";
DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
procid_str_static(&src), msg));
@@ -117,7 +119,10 @@ static void ping_message(int msg_type, struct process_id src,
BOOL message_init(void)
{
- if (tdb) return True;
+ sec_init();
+
+ if (tdb)
+ return True;
tdb = tdb_open_log(lock_path("messages.tdb"),
0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
@@ -130,7 +135,7 @@ BOOL message_init(void)
CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
- message_register(MSG_PING, ping_message);
+ message_register(MSG_PING, ping_message, NULL);
/* Register some debugging related messages */
@@ -161,9 +166,12 @@ static TDB_DATA message_key_pid(struct process_id pid)
then delete its record in the database.
****************************************************************************/
-static BOOL message_notify(struct process_id procid)
+static NTSTATUS message_notify(struct process_id procid)
{
pid_t pid = procid.pid;
+ int ret;
+ uid_t euid = geteuid();
+
/*
* Doing kill with a non-positive pid causes messages to be
* sent to places we don't want.
@@ -171,26 +179,52 @@ static BOOL message_notify(struct process_id procid)
SMB_ASSERT(pid > 0);
- if (kill(pid, SIGUSR1) == -1) {
+ if (euid != 0) {
+ become_root_uid_only();
+ }
+
+ ret = kill(pid, SIGUSR1);
+
+ if (euid != 0) {
+ unbecome_root_uid_only();
+ }
+
+ if (ret == -1) {
if (errno == ESRCH) {
- DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid));
+ DEBUG(2,("pid %d doesn't exist - deleting messages record\n",
+ (int)pid));
tdb_delete(tdb, message_key_pid(procid));
- } else {
- DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno)));
+
+ /*
+ * INVALID_HANDLE is the closest I can think of -- vl
+ */
+ return NT_STATUS_INVALID_HANDLE;
}
- return False;
+
+ DEBUG(2,("message to process %d failed - %s\n", (int)pid,
+ strerror(errno)));
+
+ /*
+ * No call to map_nt_error_from_unix -- don't want to link in
+ * errormap.o into lots of utils.
+ */
+
+ if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
+ if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return True;
+
+ return NT_STATUS_OK;
}
/****************************************************************************
Send a message to a particular pid.
****************************************************************************/
-static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
- const void *buf, size_t len,
- BOOL duplicates_allowed,
- unsigned int timeout)
+static NTSTATUS message_send_pid_internal(struct process_id pid, int msg_type,
+ const void *buf, size_t len,
+ BOOL duplicates_allowed,
+ unsigned int timeout)
{
TDB_DATA kbuf;
TDB_DATA dbuf;
@@ -219,9 +253,10 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
kbuf = message_key_pid(pid);
- dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec));
- if (!dbuf.dptr)
- return False;
+ dbuf.dptr = (char *)SMB_MALLOC(len + sizeof(rec));
+ if (!dbuf.dptr) {
+ return NT_STATUS_NO_MEMORY;
+ }
memcpy(dbuf.dptr, &rec, sizeof(rec));
if (len > 0 && buf)
@@ -236,13 +271,15 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
/* lock the record for the destination */
if (timeout) {
if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
- DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
- return False;
+ DEBUG(0,("message_send_pid_internal: failed to get "
+ "chainlock with timeout %ul.\n", timeout));
+ return NT_STATUS_IO_TIMEOUT;
}
} else {
if (tdb_chainlock(tdb, kbuf) == -1) {
- DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
- return False;
+ DEBUG(0,("message_send_pid_internal: failed to get "
+ "chainlock.\n"));
+ return NT_STATUS_LOCK_NOT_GRANTED;
}
}
tdb_append(tdb, kbuf, dbuf);
@@ -256,13 +293,15 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
/* lock the record for the destination */
if (timeout) {
if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
- DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
- return False;
+ DEBUG(0,("message_send_pid_internal: failed to get chainlock "
+ "with timeout %ul.\n", timeout));
+ return NT_STATUS_IO_TIMEOUT;
}
} else {
if (tdb_chainlock(tdb, kbuf) == -1) {
- DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
- return False;
+ DEBUG(0,("message_send_pid_internal: failed to get "
+ "chainlock.\n"));
+ return NT_STATUS_LOCK_NOT_GRANTED;
}
}
@@ -291,10 +330,11 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
if (!memcmp(ptr, &rec, sizeof(rec))) {
if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
tdb_chainunlock(tdb, kbuf);
- DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n"));
+ DEBUG(10,("message_send_pid_internal: discarding "
+ "duplicate message.\n"));
SAFE_FREE(dbuf.dptr);
SAFE_FREE(old_dbuf.dptr);
- return True;
+ return NT_STATUS_OK;
}
}
memcpy(&prec, ptr, sizeof(prec));
@@ -317,19 +357,23 @@ static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
Send a message to a particular pid - no timeout.
****************************************************************************/
-BOOL message_send_pid(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed)
+NTSTATUS message_send_pid(struct process_id pid, int msg_type, const void *buf,
+ size_t len, BOOL duplicates_allowed)
{
- return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0);
+ return message_send_pid_internal(pid, msg_type, buf, len,
+ duplicates_allowed, 0);
}
/****************************************************************************
Send a message to a particular pid, with timeout in seconds.
****************************************************************************/
-BOOL message_send_pid_with_timeout(struct process_id pid, int msg_type, const void *buf, size_t len,
- BOOL duplicates_allowed, unsigned int timeout)
+NTSTATUS message_send_pid_with_timeout(struct process_id pid, int msg_type,
+ const void *buf, size_t len,
+ BOOL duplicates_allowed, unsigned int timeout)
{
- return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout);
+ return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed,
+ timeout);
}
/****************************************************************************
@@ -441,8 +485,7 @@ static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type,
/****************************************************************************
Receive and dispatch any messages pending for this process.
- Notice that all dispatch handlers for a particular msg_type get called,
- so you can register multiple handlers for a message.
+ JRA changed Dec 13 2006. Only one message handler now permitted per type.
*NOTE*: Dispatch functions must be able to cope with incoming
messages on an *odd* byte boundary.
****************************************************************************/
@@ -454,7 +497,6 @@ void message_dispatch(void)
char *buf;
char *msgs_buf;
size_t len, total_len;
- struct dispatch_fns *dfn;
int n_handled;
if (!received_signal)
@@ -468,19 +510,25 @@ void message_dispatch(void)
return;
for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) {
+ struct dispatch_fns *dfn;
+
DEBUG(10,("message_dispatch: received msg_type=%d "
"src_pid=%u\n", msg_type,
(unsigned int) procid_to_pid(&src)));
+
n_handled = 0;
for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
if (dfn->msg_type == msg_type) {
DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type));
- dfn->fn(msg_type, src, len ? (void *)buf : NULL, len);
+ dfn->fn(msg_type, src,
+ len ? (void *)buf : NULL, len,
+ dfn->private_data);
n_handled++;
+ break;
}
}
if (!n_handled) {
- DEBUG(5,("message_dispatch: warning: no handlers registed for "
+ DEBUG(5,("message_dispatch: warning: no handler registed for "
"msg_type %d in pid %u\n",
msg_type, (unsigned int)sys_getpid()));
}
@@ -489,17 +537,27 @@ void message_dispatch(void)
}
/****************************************************************************
- Register a dispatch function for a particular message type.
+ Register/replace a dispatch function for a particular message type.
+ JRA changed Dec 13 2006. Only one message handler now permitted per type.
*NOTE*: Dispatch functions must be able to cope with incoming
messages on an *odd* byte boundary.
****************************************************************************/
void message_register(int msg_type,
void (*fn)(int msg_type, struct process_id pid,
- void *buf, size_t len))
+ void *buf, size_t len,
+ void *private_data),
+ void *private_data)
{
struct dispatch_fns *dfn;
+ for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
+ if (dfn->msg_type == msg_type) {
+ dfn->fn = fn;
+ return;
+ }
+ }
+
dfn = SMB_MALLOC_P(struct dispatch_fns);
if (dfn != NULL) {
@@ -508,6 +566,7 @@ void message_register(int msg_type,
dfn->msg_type = msg_type;
dfn->fn = fn;
+ dfn->private_data = private_data;
DLIST_ADD(dispatch_fns, dfn);
}
@@ -530,6 +589,7 @@ void message_deregister(int msg_type)
if (dfn->msg_type == msg_type) {
DLIST_REMOVE(dispatch_fns, dfn);
SAFE_FREE(dfn);
+ return;
}
}
}
@@ -551,6 +611,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void
{
struct connections_data crec;
struct msg_all *msg_all = (struct msg_all *)state;
+ NTSTATUS status;
if (dbuf.dsize != sizeof(crec))
return 0;
@@ -568,18 +629,17 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void
/* If the msg send fails because the pid was not found (i.e. smbd died),
* the msg has already been deleted from the messages.tdb.*/
- if (!message_send_pid(crec.pid, msg_all->msg_type,
- msg_all->buf, msg_all->len,
- msg_all->duplicates)) {
+ status = message_send_pid(crec.pid, msg_all->msg_type,
+ msg_all->buf, msg_all->len,
+ msg_all->duplicates);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
/* If the pid was not found delete the entry from connections.tdb */
- if (errno == ESRCH) {
- DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
- procid_str_static(&crec.pid),
- crec.cnum, crec.name));
- tdb_delete(the_tdb, kbuf);
- }
+ DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
+ procid_str_static(&crec.pid), crec.cnum, crec.name));
+ tdb_delete(the_tdb, kbuf);
}
msg_all->n_sent++;
return 0;
@@ -643,4 +703,135 @@ void message_unblock(void)
{
BlockSignals(False, SIGUSR1);
}
+
+/*
+ * Samba4 API wrapper around the Samba3 implementation. Yes, I know, we could
+ * import the whole Samba4 thing, but I want notify.c from Samba4 in first.
+ */
+
+struct messaging_callback {
+ struct messaging_callback *prev, *next;
+ uint32 msg_type;
+ void (*fn)(struct messaging_context *msg, void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id, DATA_BLOB *data);
+ void *private_data;
+};
+
+struct messaging_context {
+ struct server_id id;
+ struct messaging_callback *callbacks;
+};
+
+static int messaging_context_destructor(struct messaging_context *ctx)
+{
+ struct messaging_callback *cb;
+
+ for (cb = ctx->callbacks; cb; cb = cb->next) {
+ /*
+ * We unconditionally remove all instances of our callback
+ * from the tdb basis.
+ */
+ message_deregister(cb->msg_type);
+ }
+ return 0;
+}
+
+struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
+ struct server_id server_id,
+ struct event_context *ev)
+{
+ struct messaging_context *ctx;
+
+ if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
+ return NULL;
+ }
+
+ ctx->id = server_id;
+ talloc_set_destructor(ctx, messaging_context_destructor);
+ return ctx;
+}
+
+static void messaging_callback(int msg_type, struct process_id pid,
+ void *buf, size_t len, void *private_data)
+{
+ struct messaging_context *ctx = talloc_get_type_abort(
+ private_data, struct messaging_context);
+ struct messaging_callback *cb, *next;
+
+ for (cb = ctx->callbacks; cb; cb = next) {
+ /*
+ * Allow a callback to remove itself
+ */
+ next = cb->next;
+
+ if (msg_type == cb->msg_type) {
+ DATA_BLOB blob;
+ struct server_id id;
+
+ blob.data = (uint8 *)buf;
+ blob.length = len;
+ id.id = pid;
+
+ cb->fn(ctx, cb->private_data, msg_type, id, &blob);
+ }
+ }
+}
+
+/*
+ * Register a dispatch function for a particular message type. Allow multiple
+ * registrants
+*/
+NTSTATUS messaging_register(struct messaging_context *ctx, void *private_data,
+ uint32_t msg_type,
+ void (*fn)(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data))
+{
+ struct messaging_callback *cb;
+
+ if (!(cb = talloc(ctx, struct messaging_callback))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ cb->msg_type = msg_type;
+ cb->fn = fn;
+ cb->private_data = private_data;
+
+ DLIST_ADD(ctx->callbacks, cb);
+ message_register(msg_type, messaging_callback, ctx);
+ return NT_STATUS_OK;
+}
+
+/*
+ De-register the function for a particular message type.
+*/
+void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
+ void *private_data)
+{
+ struct messaging_callback *cb, *next;
+
+ for (cb = ctx->callbacks; cb; cb = next) {
+ next = cb->next;
+ if ((cb->msg_type == msg_type)
+ && (cb->private_data == private_data)) {
+ DLIST_REMOVE(ctx->callbacks, cb);
+ TALLOC_FREE(cb);
+ }
+ }
+}
+
+/*
+ Send a message to a particular server
+*/
+NTSTATUS messaging_send(struct messaging_context *msg,
+ struct server_id server,
+ uint32_t msg_type, DATA_BLOB *data)
+{
+ return message_send_pid_internal(server.id, msg_type, data->data,
+ data->length, True, 0);
+}
+
/** @} **/
diff --git a/source/lib/pam_errors.c b/source/lib/pam_errors.c
index 8a4c41d7df5..9d9a377a912 100644
--- a/source/lib/pam_errors.c
+++ b/source/lib/pam_errors.c
@@ -72,6 +72,13 @@ static const struct {
{NT_STATUS_ACCOUNT_LOCKED_OUT, PAM_MAXTRIES},
{NT_STATUS_NO_MEMORY, PAM_BUF_ERR},
{NT_STATUS_PASSWORD_RESTRICTION, PAM_PERM_DENIED},
+ {NT_STATUS_BACKUP_CONTROLLER, PAM_AUTHINFO_UNAVAIL},
+ {NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND, PAM_AUTHINFO_UNAVAIL},
+ {NT_STATUS_NO_LOGON_SERVERS, PAM_AUTHINFO_UNAVAIL},
+ {NT_STATUS_INVALID_WORKSTATION, PAM_PERM_DENIED},
+ {NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL},
+ {NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL},
+ {NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT, PAM_AUTHINFO_UNAVAIL},
{NT_STATUS_OK, PAM_SUCCESS}
};
diff --git a/source/lib/popt_common.c b/source/lib/popt_common.c
index d29e171be08..0c0ed86dd1f 100644
--- a/source/lib/popt_common.c
+++ b/source/lib/popt_common.c
@@ -123,7 +123,7 @@ static void popt_common_callback(poptContext con,
}
struct poptOption popt_common_connection[] = {
- { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback },
+ { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
{ "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use",
"SOCKETOPTIONS" },
{ "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" },
@@ -134,7 +134,7 @@ struct poptOption popt_common_connection[] = {
};
struct poptOption popt_common_samba[] = {
- { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback },
+ { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_callback },
{ "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" },
{ "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" },
{ "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" },
@@ -143,7 +143,7 @@ struct poptOption popt_common_samba[] = {
};
struct poptOption popt_common_version[] = {
- { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback },
+ { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
{ "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" },
POPT_TABLEEND
};
@@ -248,7 +248,7 @@ static void popt_dynconfig_callback(poptContext con,
const struct poptOption popt_common_dynconfig[] = {
- { NULL, '\0', POPT_ARG_CALLBACK, popt_dynconfig_callback },
+ { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_dynconfig_callback },
{ "sbindir", '\0' , POPT_ARG_STRING, NULL, DYN_SBINDIR,
"Path to sbin directory", "SBINDIR" },
@@ -515,7 +515,7 @@ static void popt_common_credentials_callback(poptContext con,
struct poptOption popt_common_credentials[] = {
- { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback },
+ { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_credentials_callback },
{ "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" },
{ "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" },
{ "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" },
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
index d19592e5826..c0f7857c95b 100644
--- a/source/lib/privileges.c
+++ b/source/lib/privileges.c
@@ -309,7 +309,8 @@ static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask )
check if the privilege is in the privilege list
****************************************************************************/
-static BOOL is_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
+static BOOL is_privilege_assigned( const SE_PRIV *privileges,
+ const SE_PRIV *check )
{
SE_PRIV p1, p2;
@@ -473,7 +474,7 @@ BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount)
static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
{
- PRIV_SID_LIST *priv = state;
+ PRIV_SID_LIST *priv = (PRIV_SID_LIST *)state;
int prefixlen = strlen(PRIVPREFIX);
DOM_SID sid;
fstring sid_string;
@@ -516,7 +517,9 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s
return 0;
}
- add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count );
+ if (!add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count )) {
+ return 0;
+ }
return 0;
}
@@ -740,7 +743,7 @@ NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_l
at a time here.
*****************************************************************************/
-BOOL user_has_privileges(NT_USER_TOKEN *token, const SE_PRIV *privilege)
+BOOL user_has_privileges(const NT_USER_TOKEN *token, const SE_PRIV *privilege)
{
if ( !token )
return False;
diff --git a/source/lib/readline.c b/source/lib/readline.c
index 1f599dc0a7f..24d16ea34fb 100644
--- a/source/lib/readline.c
+++ b/source/lib/readline.c
@@ -113,8 +113,10 @@ char *smb_readline(const char *prompt, void (*callback)(void),
rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn;
}
+#if HAVE_DECL_RL_EVENT_HOOK
if (callback)
rl_event_hook = (Function *)callback;
+#endif
ret = readline(prompt);
if (ret && *ret)
add_history(ret);
@@ -154,7 +156,7 @@ history
****************************************************************************/
int cmd_history(void)
{
-#if defined(HAVE_LIBREADLINE)
+#if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
HIST_ENTRY **hlist;
int i;
diff --git a/source/lib/replace.c b/source/lib/replace.c
deleted file mode 100644
index 19b37af9386..00000000000
--- a/source/lib/replace.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- replacement routines for broken systems
- Copyright (C) Andrew Tridgell 1992-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
- void replace_dummy(void);
- void replace_dummy(void) {}
-
-#ifndef HAVE_FTRUNCATE
- /*******************************************************************
-ftruncate for operating systems that don't have it
-********************************************************************/
- int ftruncate(int f,SMB_OFF_T l)
-{
-#ifdef HAVE_CHSIZE
- return chsize(f,l);
-#else
- struct flock fl;
-
- fl.l_whence = 0;
- fl.l_len = 0;
- fl.l_start = l;
- fl.l_type = F_WRLCK;
- return fcntl(f, F_FREESP, &fl);
-#endif
-}
-#endif /* HAVE_FTRUNCATE */
-
-#ifndef HAVE_STRLCPY
-/* like strncpy but does not 0 fill the buffer and always null
- terminates. bufsize is the size of the destination buffer */
- size_t strlcpy(char *d, const char *s, size_t bufsize)
-{
- size_t len = strlen(s);
- size_t ret = len;
- if (bufsize <= 0) return 0;
- if (len >= bufsize) len = bufsize-1;
- memcpy(d, s, len);
- d[len] = 0;
- return ret;
-}
-#endif
-
-#ifndef HAVE_STRLCAT
-/* like strncat but does not 0 fill the buffer and always null
- terminates. bufsize is the length of the buffer, which should
- be one more than the maximum resulting string length */
- size_t strlcat(char *d, const char *s, size_t bufsize)
-{
- size_t len1 = strlen(d);
- size_t len2 = strlen(s);
- size_t ret = len1 + len2;
-
- if (len1 >= bufsize) {
- return 0;
- }
- if (len1+len2 >= bufsize) {
- len2 = bufsize - (len1+1);
- }
- if (len2 > 0) {
- memcpy(d+len1, s, len2);
- d[len1+len2] = 0;
- }
- return ret;
-}
-#endif
-
-#ifndef HAVE_MKTIME
-/*******************************************************************
-a mktime() replacement for those who don't have it - contributed by
-C.A. Lademann <cal@zls.com>
-Corrections by richard.kettlewell@kewill.com
-********************************************************************/
-
-#define MINUTE 60
-#define HOUR 60*MINUTE
-#define DAY 24*HOUR
-#define YEAR 365*DAY
- time_t mktime(struct tm *t)
-{
- struct tm *u;
- time_t epoch = 0;
- int n;
- int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- y, m, i;
-
- if(t->tm_year < 70) {
- return((time_t)-1);
- }
-
- n = t->tm_year + 1900 - 1;
- epoch = (t->tm_year - 70) * YEAR + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
-
- y = t->tm_year + 1900;
- m = 0;
-
- for(i = 0; i < t->tm_mon; i++) {
- epoch += mon [m] * DAY;
- if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
- epoch += DAY;
- }
-
- if(++m > 11) {
- m = 0;
- y++;
- }
- }
-
- epoch += (t->tm_mday - 1) * DAY;
- epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
-
- if((u = localtime(&epoch)) != NULL) {
- t->tm_sec = u->tm_sec;
- t->tm_min = u->tm_min;
- t->tm_hour = u->tm_hour;
- t->tm_mday = u->tm_mday;
- t->tm_mon = u->tm_mon;
- t->tm_year = u->tm_year;
- t->tm_wday = u->tm_wday;
- t->tm_yday = u->tm_yday;
- t->tm_isdst = u->tm_isdst;
- }
-
- return(epoch);
-}
-#endif /* !HAVE_MKTIME */
-
-
-
-#ifndef HAVE_RENAME
-/* Rename a file. (from libiberty in GNU binutils) */
- int rename(const char *zfrom, const char *zto)
-{
- if (link (zfrom, zto) < 0) {
- if (errno != EEXIST) {
- return -1;
- }
- if (unlink (zto) < 0 || link (zfrom, zto) < 0) {
- return -1;
- }
- }
- return unlink (zfrom);
-}
-#endif /* HAVE_RENAME */
-
-
-#ifndef HAVE_INNETGR
-#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
-/*
- * Search for a match in a netgroup. This replaces it on broken systems.
- */
- int innetgr(const char *group,const char *host,const char *user,const char *dom)
-{
- char *hst, *usr, *dm;
-
- setnetgrent(group);
- while (getnetgrent(&hst, &usr, &dm)) {
- if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
- ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
- ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
- endnetgrent();
- return (1);
- }
- }
- endnetgrent();
- return (0);
-}
-#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
-#endif /* HAVE_INNETGR */
-
-
-
-#ifndef HAVE_INITGROUPS
-/****************************************************************************
- some systems don't have an initgroups call
-****************************************************************************/
- int initgroups(char *name,gid_t id)
-{
-#ifndef HAVE_SETGROUPS
- static int done;
- if (!done) {
- DEBUG(1,("WARNING: running without setgroups\n"));
- done=1;
- }
- /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
- return(0);
-#else /* HAVE_SETGROUPS */
- gid_t *grouplst = NULL;
- int max_gr = groups_max();
- int ret;
- int i,j;
- struct group *g;
- char *gr;
-
- if((grouplst = SMB_MALLOC_ARRAY(gid_t, max_gr)) == NULL) {
- DEBUG(0,("initgroups: malloc fail !\n"));
- return -1;
- }
-
- grouplst[0] = id;
- i = 1;
- while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
- if (g->gr_gid == id)
- continue;
- j = 0;
- gr = g->gr_mem[0];
- while (gr && (*gr != (char)NULL)) {
- if (strcmp(name,gr) == 0) {
- grouplst[i] = g->gr_gid;
- i++;
- gr = (char *)NULL;
- break;
- }
- gr = g->gr_mem[++j];
- }
- }
- endgrent();
- ret = sys_setgroups(i,grouplst);
- SAFE_FREE(grouplst);
- return ret;
-#endif /* HAVE_SETGROUPS */
-}
-#endif /* HAVE_INITGROUPS */
-
-
-#if (defined(SecureWare) && defined(SCO))
-/* This is needed due to needing the nap() function but we don't want
- to include the Xenix libraries since that will break other things...
- BTW: system call # 0x0c28 is the same as calling nap() */
- long nap(long milliseconds) {
- return syscall(0x0c28, milliseconds);
- }
-#endif
-
-
-#ifndef HAVE_MEMMOVE
-/*******************************************************************
-safely copies memory, ensuring no overlap problems.
-this is only used if the machine does not have it's own memmove().
-this is not the fastest algorithm in town, but it will do for our
-needs.
-********************************************************************/
- void *memmove(void *dest,const void *src,int size)
-{
- unsigned long d,s;
- int i;
- if (dest==src || !size) return(dest);
-
- d = (unsigned long)dest;
- s = (unsigned long)src;
-
- if ((d >= (s+size)) || (s >= (d+size))) {
- /* no overlap */
- memcpy(dest,src,size);
- return(dest);
- }
-
- if (d < s) {
- /* we can forward copy */
- if (s-d >= sizeof(int) &&
- !(s%sizeof(int)) &&
- !(d%sizeof(int)) &&
- !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=0;i<size;i++) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=0;i<size;i++) cdest[i] = csrc[i];
- }
- } else {
- /* must backward copy */
- if (d-s >= sizeof(int) &&
- !(s%sizeof(int)) &&
- !(d%sizeof(int)) &&
- !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=size-1;i>=0;i--) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
- }
- }
- return(dest);
-}
-#endif /* HAVE_MEMMOVE */
-
-#ifndef HAVE_STRDUP
-/****************************************************************************
-duplicate a string
-****************************************************************************/
-
-#ifdef strdup
-#undef strdup
-#endif
-
- char *strdup(const char *s)
-{
- size_t len;
- char *ret;
-
- if (!s) return(NULL);
-
- len = strlen(s)+1;
- ret = (char *)SMB_MALLOC(len);
- if (!ret) return(NULL);
- memcpy(ret,s,len);
- return(ret);
-}
-#endif /* HAVE_STRDUP */
-
-#ifdef REPLACE_INET_NTOA
-char *rep_inet_ntoa(struct in_addr ip)
-{
- unsigned char *p = (unsigned char *)&ip.s_addr;
- static char buf[18];
- slprintf(buf, 17, "%d.%d.%d.%d",
- (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
- return buf;
-}
-#endif /* REPLACE_INET_NTOA */
-
-#ifndef HAVE_STRTOUL
-#ifndef ULONG_MAX
-#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
-#endif
-
-/*
- * Convert a string to an unsigned long integer.
- * Taken from libg++ - libiberty code.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
- unsigned long strtoul(const char *nptr, char **endptr, int base)
-{
- const char *s = nptr;
- unsigned long acc;
- int c;
- unsigned long cutoff;
- int neg = 0, any, cutlim;
-
- /*
- * See strtol for comments as to the logic used.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
- cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper_ascii(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = ULONG_MAX;
- errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (char *) (any ? s - 1 : nptr);
- return (acc);
-}
-#endif /* HAVE_STRTOUL */
-
-#ifndef HAVE_SETLINEBUF
- int setlinebuf(FILE *stream)
-{
- return setvbuf(stream, (char *)NULL, _IOLBF, 0);
-}
-#endif /* HAVE_SETLINEBUF */
-
-#ifndef HAVE_VSYSLOG
-#ifdef HAVE_SYSLOG
- void vsyslog (int facility_priority, const char *format, va_list arglist)
-{
- char *msg = NULL;
- vasprintf(&msg, format, arglist);
- if (!msg)
- return;
- syslog(facility_priority, "%s", msg);
- SAFE_FREE(msg);
-}
-#endif /* HAVE_SYSLOG */
-#endif /* HAVE_VSYSLOG */
diff --git a/source/lib/replace/.checker_innocent b/source/lib/replace/.checker_innocent
new file mode 100644
index 00000000000..e6191765409
--- /dev/null
+++ b/source/lib/replace/.checker_innocent
@@ -0,0 +1,4 @@
+>>>MISTAKE21_create_files_6a9e68ada99a97cb
+>>>MISTAKE21_os2_delete_9b2bfa7f38711d09
+>>>MISTAKE21_os2_delete_2fcc29aaa99a97cb
+>>>SECURITY2_os2_delete_9b2bfa7f1c9396ca
diff --git a/source/lib/replace/Makefile.in b/source/lib/replace/Makefile.in
new file mode 100644
index 00000000000..10ba5b9415a
--- /dev/null
+++ b/source/lib/replace/Makefile.in
@@ -0,0 +1,60 @@
+#!gmake
+#
+CC = @CC@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+VPATH = @libreplacedir@
+srcdir = @srcdir@
+builddir = @builddir@
+INSTALL = @INSTALL@
+
+.PHONY: test
+
+CFLAGS=-I. -I@libreplacedir@ @CFLAGS@
+
+OBJS = @LIBREPLACEOBJ@
+
+all: showflags libreplace.a testsuite
+
+showflags:
+ @echo 'libreplace will be compiled with flags:'
+ @echo ' CC = $(CC)'
+ @echo ' CFLAGS = $(CFLAGS)'
+ @echo ' LIBS = $(LIBS)'
+
+install: all
+ mkdir -p $(libdir)
+ $(INSTALL) libreplace.a $(libdir)
+
+libreplace.a: $(OBJS)
+ ar -rcsv $@ $(OBJS)
+
+test: all
+ ./testsuite
+
+installcheck: install test
+
+TEST_OBJS = test/testsuite.o test/os2_delete.o
+
+testsuite: libreplace.a $(TEST_OBJS)
+ $(CC) -o testsuite $(TEST_OBJS) -L. -lreplace
+
+.c.o:
+ @echo Compiling $*.c
+ @mkdir -p `dirname $@`
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+ rm -f *.o test/*.o *.a testsuite
+ rm -f testfile.dat
+
+distclean: clean
+ rm -f *~ */*~
+ rm -f config.log config.status config.h config.cache
+ rm -f Makefile
+
+realdistclean: distclean
+ rm -f configure config.h.in
diff --git a/source/lib/replace/README b/source/lib/replace/README
new file mode 100644
index 00000000000..a313984c8ea
--- /dev/null
+++ b/source/lib/replace/README
@@ -0,0 +1,88 @@
+This subsystem ensures that we can always use a certain core set of
+functions and types, that are either provided by the OS or by replacement
+functions / definitions in this subsystem. The aim is to try to stick
+to POSIX functions in here as much as possible. Convenience functions
+that are available on no platform at all belong in other subsystems
+(such as LIBUTIL).
+
+The following functions are guaranteed:
+
+ftruncate
+strlcpy
+strlcat
+mktime
+rename
+innetgr
+initgroups
+memmove
+strdup
+inet_ntoa
+setlinebuf
+vsyslog
+timegm
+setenv
+strndup
+strnlen
+waitpid
+seteuid
+setegid
+asprintf
+snprintf
+vasprintf
+vsnprintf
+opendir
+readdir
+telldir
+seekdir
+closedir
+dlopen
+dlclose
+dlsym
+dlerror
+chroot
+bzero
+strerror
+errno
+mkdtemp
+mkstemp (a secure one!)
+pread
+pwrite
+getpass
+readline (the library)
+inet_ntoa
+strtoll
+strtoull
+socketpair
+
+Types:
+bool
+socklen_t
+uint_t
+uint{8,16,32,64}_t
+int{8,16,32,64}_t
+intptr_t
+
+Constants:
+PATH_NAME_MAX
+UINT{16,32,64}_MAX
+INT32_MAX
+RTLD_LAZY
+HOST_NAME_MAX
+UINT16_MAX
+UINT32_MAX
+UINT64_MAX
+CHAR_BIT
+
+Macros:
+va_copy
+__FUNCTION__
+__STRING
+MIN
+MAX
+QSORT_CAST
+
+Prerequisites:
+memset (for bzero)
+syslog (for vsyslog)
+setnetgrent, getnetgrent, endnetgrent (for innetgr)
+mktemp (for mkstemp and mkdtemp)
diff --git a/source/lib/replace/aclocal.m4 b/source/lib/replace/aclocal.m4
new file mode 100644
index 00000000000..5605e476bab
--- /dev/null
+++ b/source/lib/replace/aclocal.m4
@@ -0,0 +1 @@
+m4_include(libreplace.m4)
diff --git a/source/lib/replace/autoconf-2.60.m4 b/source/lib/replace/autoconf-2.60.m4
new file mode 100644
index 00000000000..5360fff5d24
--- /dev/null
+++ b/source/lib/replace/autoconf-2.60.m4
@@ -0,0 +1,197 @@
+# _AC_C_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST,
+# ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE)
+# --------------------------------------------------------------
+# Check whether the C compiler accepts features of STANDARD (e.g `c89', `c99')
+# by trying to compile a program of TEST-PROLOGUE and TEST-BODY. If this fails,
+# try again with each compiler option in the space-separated OPTION-LIST; if one
+# helps, append it to CC. If eventually successful, run ACTION-IF-AVAILABLE,
+# else ACTION-IF-UNAVAILABLE.
+AC_DEFUN([_AC_C_STD_TRY],
+[AC_MSG_CHECKING([for $CC option to accept ISO ]m4_translit($1, [c], [C]))
+AC_CACHE_VAL(ac_cv_prog_cc_$1,
+[ac_cv_prog_cc_$1=no
+ac_save_CC=$CC
+AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])])
+for ac_arg in '' $4
+do
+ CC="$ac_save_CC $ac_arg"
+ _AC_COMPILE_IFELSE([], [ac_cv_prog_cc_$1=$ac_arg])
+ test "x$ac_cv_prog_cc_$1" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+])# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_$1" in
+ x)
+ AC_MSG_RESULT([none needed]) ;;
+ xno)
+ AC_MSG_RESULT([unsupported]) ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_$1"
+ AC_MSG_RESULT([$ac_cv_prog_cc_$1]) ;;
+esac
+AS_IF([test "x$ac_cv_prog_cc_$1" != xno], [$5], [$6])
+])# _AC_C_STD_TRY
+
+# _AC_PROG_CC_C99 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE])
+# ----------------------------------------------------------------
+# If the C compiler is not in ISO C99 mode by default, try to add an
+# option to output variable CC to make it so. This macro tries
+# various options that select ISO C99 on some system or another. It
+# considers the compiler to be in ISO C99 mode if it handles mixed
+# code and declarations, _Bool, inline and restrict.
+AC_DEFUN([_AC_PROG_CC_C99],
+[_AC_C_STD_TRY([c99],
+[[#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict(ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy work.
+static void
+test_varargs(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg(args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg(args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = (float) va_arg(args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end(args_copy);
+ va_end(args);
+}
+]],
+[[
+ // Check bool and long long datatypes.
+ _Bool success = false;
+ long long int bignum = -1234567890LL;
+ unsigned long long int ubignum = 1234567890uLL;
+
+ // Check restrict.
+ if (test_restrict("String literal") != 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs("s, d' f .", "string", 65, 34.234);
+
+ // Check incomplete arrays work.
+ struct incomplete_array *ia =
+ malloc(sizeof(struct incomplete_array) + (sizeof(double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = (double) i * 1.234;
+
+ // Check named initialisers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[43] = 543;
+
+ // work around unused variable warnings
+ return bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x';
+]],
+dnl Try
+dnl GCC -std=gnu99 (unused restrictive modes: -std=c99 -std=iso9899:1999)
+dnl AIX -qlanglvl=extc99 (unused restrictive mode: -qlanglvl=stdc99)
+dnl Intel ICC -c99
+dnl IRIX -c99
+dnl Solaris (unused because it causes the compiler to assume C99 semantics for
+dnl library functions, and this is invalid before Solaris 10: -xc99)
+dnl Tru64 -c99
+dnl with extended modes being tried first.
+[[-std=gnu99 -c99 -qlanglvl=extc99]], [$1], [$2])[]dnl
+])# _AC_PROG_CC_C99
+
+# AC_PROG_CC_C99
+# --------------
+AC_DEFUN([AC_PROG_CC_C99],
+[ AC_REQUIRE([AC_PROG_CC])dnl
+ _AC_PROG_CC_C99
+])
+
+# AC_USE_SYSTEM_EXTENSIONS
+# ------------------------
+# Enable extensions on systems that normally disable them,
+# typically due to standards-conformance issues.
+AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS],
+[
+ AC_BEFORE([$0], [AC_COMPILE_IFELSE])
+ AC_BEFORE([$0], [AC_RUN_IFELSE])
+
+ AC_REQUIRE([AC_GNU_SOURCE])
+ AC_REQUIRE([AC_AIX])
+ AC_REQUIRE([AC_MINIX])
+
+ AH_VERBATIM([__EXTENSIONS__],
+[/* Enable extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif])
+ AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
+ [ac_cv_safe_to_define___extensions__],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([
+# define __EXTENSIONS__ 1
+ AC_INCLUDES_DEFAULT])],
+ [ac_cv_safe_to_define___extensions__=yes],
+ [ac_cv_safe_to_define___extensions__=no])])
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ AC_DEFINE([__EXTENSIONS__])
+ AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
+])
diff --git a/source/lib/replace/autogen.sh b/source/lib/replace/autogen.sh
new file mode 100755
index 00000000000..d46a4279f30
--- /dev/null
+++ b/source/lib/replace/autogen.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f configure config.h.in
+
+autoheader || exit 1
+autoconf || exit 1
+
+rm -rf autom4te.cache
+
+echo "Now run ./configure and then make."
+exit 0
+
diff --git a/source/lib/replace/config.guess b/source/lib/replace/config.guess
new file mode 100755
index 00000000000..ad5281e66e9
--- /dev/null
+++ b/source/lib/replace/config.guess
@@ -0,0 +1,1466 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-08-03'
+
+# This file 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/source/lib/replace/config.sub b/source/lib/replace/config.sub
new file mode 100755
index 00000000000..1c366dfde9a
--- /dev/null
+++ b/source/lib/replace/config.sub
@@ -0,0 +1,1579 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-07-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/source/lib/replace/configure.ac b/source/lib/replace/configure.ac
new file mode 100644
index 00000000000..48fb7ce2594
--- /dev/null
+++ b/source/lib/replace/configure.ac
@@ -0,0 +1,22 @@
+AC_PREREQ(2.50)
+AC_INIT(replace.c)
+AC_CONFIG_SRCDIR([replace.c])
+AC_CONFIG_HEADER(config.h)
+
+AC_LIBREPLACE_ALL_CHECKS
+
+if test "$ac_cv_prog_gcc" = yes; then
+ CFLAGS="$CFLAGS -Wall"
+ CFLAGS="$CFLAGS -W"
+ CFLAGS="$CFLAGS -Wshadow"
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
+ CFLAGS="$CFLAGS -Wpointer-arith"
+ CFLAGS="$CFLAGS -Wcast-qual"
+ CFLAGS="$CFLAGS -Wcast-align"
+ CFLAGS="$CFLAGS -Wwrite-strings"
+ CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+ CFLAGS="$CFLAGS -Wformat=2"
+ CFLAGS="$CFLAGS -Wno-format-y2k"
+fi
+
+AC_OUTPUT(Makefile)
diff --git a/source/lib/replace/dlfcn.c b/source/lib/replace/dlfcn.c
new file mode 100644
index 00000000000..22f9f8bf79b
--- /dev/null
+++ b/source/lib/replace/dlfcn.c
@@ -0,0 +1,54 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba system utilities
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 1998-2002
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "replace.h"
+
+#ifndef HAVE_DLOPEN
+void *rep_dlopen(const char *name, int flags)
+{
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_DLSYM
+void *rep_dlsym(void *handle, const char *symbol)
+{
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_DLERROR
+char *rep_dlerror(void)
+{
+ return "dynamic loading of objects not supported on this platform";
+}
+#endif
+
+#ifndef HAVE_DLCLOSE
+int rep_dlclose(void *handle)
+{
+ return 0;
+}
+#endif
diff --git a/source/lib/replace/dlfcn.m4 b/source/lib/replace/dlfcn.m4
new file mode 100644
index 00000000000..2d5b2c5141a
--- /dev/null
+++ b/source/lib/replace/dlfcn.m4
@@ -0,0 +1,20 @@
+dnl dummies provided by dlfcn.c if not available
+save_LIBS="$LIBS"
+LIBS=""
+
+AC_SEARCH_LIBS(dlopen, dl)
+
+if test "$ac_cv_search_dlopen" != no; then
+ AC_CHECK_HEADERS(dlfcn.h)
+
+ libreplace_cv_dlfcn=no
+ AC_CHECK_FUNCS([dlopen dlsym dlerror dlclose],[],[libreplace_cv_dlfcn=yes])
+
+ if test x"${libreplace_cv_dlfcn}" = x"yes";then
+ LIBREPLACEOBJ="${LIBREPLACEOBJ} dlfcn.o"
+ fi
+fi
+
+LIBDL="$LIBS"
+AC_SUBST(LIBDL)
+LIBS="$save_LIBS"
diff --git a/source/lib/replace/getpass.c b/source/lib/replace/getpass.c
new file mode 100644
index 00000000000..2ccbf7b7336
--- /dev/null
+++ b/source/lib/replace/getpass.c
@@ -0,0 +1,212 @@
+/* Copyright (C) 1992-1998 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Modified to use with samba by Jeremy Allison, 8th July 1995. */
+
+#include "replace.h"
+
+#if defined(HAVE_TERMIOS_H)
+/* POSIX terminal handling. */
+#include <termios.h>
+#elif defined(HAVE_TERMIO_H)
+/* Older SYSV terminal handling - don't use if we can avoid it. */
+#include <termio.h>
+#elif defined(HAVE_SYS_TERMIO_H)
+/* Older SYSV terminal handling - don't use if we can avoid it. */
+#include <sys/termio.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+/*
+ * Define additional missing types
+ */
+#ifndef HAVE_SIG_ATOMIC_T_TYPE
+typedef int sig_atomic_t;
+#endif
+
+#ifndef SIGCLD
+#define SIGCLD SIGCHLD
+#endif
+
+#ifndef SIGNAL_CAST
+#define SIGNAL_CAST (RETSIGTYPE (*)(int))
+#endif
+
+#ifdef REPLACE_GETPASS
+
+#ifdef SYSV_TERMIO
+
+/* SYSTEM V TERMIO HANDLING */
+
+static struct termio t;
+
+#define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
+#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
+#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
+
+#ifndef TCSAFLUSH
+#define TCSAFLUSH 1
+#endif
+
+#ifndef TCSANOW
+#define TCSANOW 0
+#endif
+
+static int tcgetattr(int fd, struct termio *_t)
+{
+ return ioctl(fd, TCGETA, _t);
+}
+
+static int tcsetattr(int fd, int flags, struct termio *_t)
+{
+ if(flags & TCSAFLUSH)
+ ioctl(fd, TCFLSH, TCIOFLUSH);
+ return ioctl(fd, TCSETS, _t);
+}
+
+#elif !defined(TCSAFLUSH)
+
+/* BSD TERMIO HANDLING */
+
+static struct sgttyb t;
+
+#define ECHO_IS_ON(t) ((t).sg_flags & ECHO)
+#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO)
+#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO)
+
+#define TCSAFLUSH 1
+#define TCSANOW 0
+
+static int tcgetattr(int fd, struct sgttyb *_t)
+{
+ return ioctl(fd, TIOCGETP, (char *)_t);
+}
+
+static int tcsetattr(int fd, int flags, struct sgttyb *_t)
+{
+ return ioctl(fd, TIOCSETP, (char *)_t);
+}
+
+#else /* POSIX TERMIO HANDLING */
+#define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
+#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
+#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
+
+static struct termios t;
+#endif /* SYSV_TERMIO */
+
+static void catch_signal(int signum,void (*handler)(int ))
+{
+#ifdef HAVE_SIGACTION
+ struct sigaction act;
+ struct sigaction oldact;
+
+ memset(&act, 0, sizeof(act));
+
+ act.sa_handler = handler;
+#ifdef SA_RESTART
+ /*
+ * We *want* SIGALRM to interrupt a system call.
+ */
+ if(signum != SIGALRM)
+ act.sa_flags = SA_RESTART;
+#endif
+ sigemptyset(&act.sa_mask);
+ sigaddset(&act.sa_mask,signum);
+ sigaction(signum,&act,&oldact);
+ return oldact.sa_handler;
+#else /* !HAVE_SIGACTION */
+ /* FIXME: need to handle sigvec and systems with broken signal() */
+ return signal(signum, handler);
+#endif
+}
+
+char *getsmbpass(const char *prompt)
+{
+ FILE *in, *out;
+ int echo_off;
+ static char buf[256];
+ static size_t bufsize = sizeof(buf);
+ size_t nread;
+
+ /* Catch problematic signals */
+ catch_signal(SIGINT, SIGNAL_CAST SIG_IGN);
+
+ /* Try to write to and read from the terminal if we can.
+ If we can't open the terminal, use stderr and stdin. */
+
+ in = fopen ("/dev/tty", "w+");
+ if (in == NULL)
+ {
+ in = stdin;
+ out = stderr;
+ }
+ else
+ out = in;
+
+ setvbuf(in, NULL, _IONBF, 0);
+
+ /* Turn echoing off if it is on now. */
+
+ if (tcgetattr (fileno (in), &t) == 0)
+ {
+ if (ECHO_IS_ON(t))
+ {
+ TURN_ECHO_OFF(t);
+ echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0;
+ TURN_ECHO_ON(t);
+ }
+ else
+ echo_off = 0;
+ }
+ else
+ echo_off = 0;
+
+ /* Write the prompt. */
+ fputs (prompt, out);
+ fflush (out);
+
+ /* Read the password. */
+ buf[0] = 0;
+ fgets(buf, bufsize, in);
+ nread = strlen(buf);
+ if (buf[nread - 1] == '\n')
+ buf[nread - 1] = '\0';
+
+ /* Restore echoing. */
+ if (echo_off)
+ (void) tcsetattr (fileno (in), TCSANOW, &t);
+
+ if (in != stdin)
+ /* We opened the terminal; now close it. */
+ fclose (in);
+
+ /* Catch problematic signals */
+ catch_signal(SIGINT, SIGNAL_CAST SIG_DFL);
+
+ printf("\n");
+ return buf;
+}
+
+#else
+ void getsmbpasswd_dummy(void);
+ void getsmbpasswd_dummy(void) {;}
+#endif
diff --git a/source/lib/replace/getpass.m4 b/source/lib/replace/getpass.m4
new file mode 100644
index 00000000000..20d04a63f65
--- /dev/null
+++ b/source/lib/replace/getpass.m4
@@ -0,0 +1,17 @@
+AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS -I$libreplacedir/"
+AC_TRY_COMPILE([
+#include "confdefs.h"
+#define _LIBREPLACE_REPLACE_H
+#define REPLACE_GETPASS 1
+#define main dont_declare_main
+#include "$libreplacedir/getpass.c"
+#undef main
+],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no)
+CPPFLAGS="$SAVE_CPPFLAGS"
+])
+if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then
+ AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced])
+ LIBREPLACEOBJ="${LIBREPLACEOBJ} getpass.o"
+fi
diff --git a/source/lib/replace/install-sh b/source/lib/replace/install-sh
new file mode 100755
index 00000000000..58719246f04
--- /dev/null
+++ b/source/lib/replace/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/source/lib/replace/libreplace.m4 b/source/lib/replace/libreplace.m4
new file mode 100644
index 00000000000..3328dea95e8
--- /dev/null
+++ b/source/lib/replace/libreplace.m4
@@ -0,0 +1,355 @@
+AC_DEFUN_ONCE(AC_LIBREPLACE_LOCATION_CHECKS,
+[
+echo "LIBREPLACE_LOCATION_CHECKS: START"
+
+dnl find the libreplace sources. This is meant to work both for
+dnl libreplace standalone builds, and builds of packages using libreplace
+libreplacedir=""
+libreplacepaths="$srcdir $srcdir/lib/replace $srcdir/libreplace $srcdir/../libreplace $srcdir/../replace"
+for d in $libreplacepaths; do
+ if test -f "$d/replace.c"; then
+ libreplacedir="$d"
+ AC_SUBST(libreplacedir)
+ break;
+ fi
+done
+if test x"$libreplacedir" = "x"; then
+ AC_MSG_ERROR([cannot find libreplace in $libreplacepaths])
+fi
+LIBREPLACEOBJ="replace.o"
+AC_SUBST(LIBREPLACEOBJ)
+
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+echo "LIBREPLACE_LOCATION_CHECKS: END"
+]) dnl end AC_LIBREPLACE_LOCATION_CHECKS
+
+
+AC_DEFUN_ONCE(AC_LIBREPLACE_BROKEN_CHECKS,
+[
+echo "LIBREPLACE_BROKEN_CHECKS: START"
+
+dnl find the libreplace sources. This is meant to work both for
+dnl libreplace standalone builds, and builds of packages using libreplace
+libreplacedir=""
+for d in "$srcdir" "$srcdir/lib/replace" "$srcdir/libreplace" "$srcdir/../libreplace" "$srcdir/../replace"; do
+ if test -f "$d/replace.c"; then
+ libreplacedir="$d"
+ AC_SUBST(libreplacedir)
+ break;
+ fi
+done
+LIBREPLACEOBJ="replace.o"
+AC_SUBST(LIBREPLACEOBJ)
+
+LIBREPLACEOBJ="${LIBREPLACEOBJ} snprintf.o"
+
+AC_TYPE_SIGNAL
+AC_TYPE_UID_T
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_TYPE_PID_T
+AC_STRUCT_ST_RDEV
+AC_CHECK_TYPE(ino_t,unsigned)
+AC_CHECK_TYPE(loff_t,off_t)
+AC_CHECK_TYPE(offset_t,loff_t)
+
+AC_FUNC_MEMCMP
+
+AC_CHECK_FUNCS(pipe strftime srandom random srand rand usleep setbuffer lstat getpgrp)
+
+AC_CHECK_HEADERS(stdbool.h sys/select.h)
+AC_CHECK_HEADERS(setjmp.h)
+
+AC_CHECK_TYPE(bool,
+[AC_DEFINE(HAVE_BOOL, 1, [Whether the bool type is available])],,
+[
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif]
+)
+
+AC_CHECK_TYPE(_Bool,
+[AC_DEFINE(HAVE__Bool, 1, [Whether the _Bool type is available])],,
+[
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif]
+)
+
+AC_CACHE_CHECK([for working mmap],samba_cv_HAVE_MMAP,[
+AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"],
+ samba_cv_HAVE_MMAP=yes,samba_cv_HAVE_MMAP=no,samba_cv_HAVE_MMAP=cross)])
+if test x"$samba_cv_HAVE_MMAP" = x"yes"; then
+ AC_DEFINE(HAVE_MMAP,1,[Whether mmap works])
+fi
+
+
+AC_CHECK_HEADERS(sys/syslog.h syslog.h)
+AC_CHECK_HEADERS(sys/time.h time.h)
+AC_CHECK_HEADERS(stdarg.h vararg.h)
+AC_CHECK_HEADERS(sys/socket.h netinet/in.h netdb.h arpa/inet.h)
+AC_CHECK_HEADERS(netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h)
+AC_CHECK_HEADERS(sys/sockio.h sys/un.h)
+
+
+dnl we need to check that net/if.h really can be used, to cope with hpux
+dnl where including it always fails
+AC_CACHE_CHECK([for usable net/if.h],libreplace_cv_USABLE_NET_IF_H,[
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ AC_INCLUDES_DEFAULT
+ #if HAVE_SYS_SOCKET_H
+ # include <sys/socket.h>
+ #endif
+ #include <net/if.h>
+ int main(void) {return 0;}])],
+ [libreplace_cv_USABLE_NET_IF_H=yes],
+ [libreplace_cv_USABLE_NET_IF_H=no]
+ )
+])
+if test x"$libreplace_cv_USABLE_NET_IF_H" = x"yes";then
+ AC_DEFINE(HAVE_NET_IF_H, 1, usability of net/if.h)
+fi
+
+AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[
+AC_TRY_RUN([
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+main() { struct in_addr ip; ip.s_addr = 0x12345678;
+if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
+ strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
+exit(1);}],
+ samba_cv_REPLACE_INET_NTOA=yes,samba_cv_REPLACE_INET_NTOA=no,samba_cv_REPLACE_INET_NTOA=cross)])
+if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then
+ AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced])
+fi
+
+dnl Provided by replace.c:
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <sys/socket.h>],
+[socklen_t foo;],,
+[AC_DEFINE(socklen_t, int,[Socket length type])])
+
+AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror)
+AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename)
+AC_CHECK_FUNCS(waitpid strlcpy strlcat innetgr initgroups memmove strdup)
+AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp socketpair)
+AC_HAVE_DECL(setresuid, [#include <unistd.h>])
+AC_HAVE_DECL(setresgid, [#include <unistd.h>])
+AC_HAVE_DECL(errno, [#include <errno.h>])
+
+AC_CACHE_CHECK([for secure mkstemp],samba_cv_HAVE_SECURE_MKSTEMP,[
+AC_TRY_RUN([#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+main() {
+ struct stat st;
+ char tpl[20]="/tmp/test.XXXXXX";
+ int fd = mkstemp(tpl);
+ if (fd == -1) exit(1);
+ unlink(tpl);
+ if (fstat(fd, &st) != 0) exit(1);
+ if ((st.st_mode & 0777) != 0600) exit(1);
+ exit(0);
+}],
+samba_cv_HAVE_SECURE_MKSTEMP=yes,
+samba_cv_HAVE_SECURE_MKSTEMP=no,
+samba_cv_HAVE_SECURE_MKSTEMP=cross)])
+if test x"$samba_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
+ AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure])
+fi
+
+dnl Provided by snprintf.c:
+AC_CHECK_HEADERS(stdio.h strings.h)
+AC_CHECK_DECLS([snprintf, vsnprintf, asprintf, vasprintf])
+AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf)
+
+AC_CACHE_CHECK([for C99 vsnprintf],samba_cv_HAVE_C99_VSNPRINTF,[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+void foo(const char *format, ...) {
+ va_list ap;
+ int len;
+ char buf[20];
+ long long l = 1234567890;
+ l *= 100;
+
+ va_start(ap, format);
+ len = vsnprintf(buf, 0, format, ap);
+ va_end(ap);
+ if (len != 5) exit(1);
+
+ va_start(ap, format);
+ len = vsnprintf(0, 0, format, ap);
+ va_end(ap);
+ if (len != 5) exit(2);
+
+ if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(3);
+
+ if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(4);
+ if (snprintf(buf, 20, "%zu", 123456789) != 9 || strcmp(buf, "123456789") != 0) exit(5);
+ if (snprintf(buf, 20, "%2\$d %1\$d", 3, 4) != 3 || strcmp(buf, "4 3") != 0) exit(6);
+ if (snprintf(buf, 20, "%s", 0) < 3) exit(7);
+
+ exit(0);
+}
+main() { foo("hello"); }
+],
+samba_cv_HAVE_C99_VSNPRINTF=yes,samba_cv_HAVE_C99_VSNPRINTF=no,samba_cv_HAVE_C99_VSNPRINTF=cross)])
+if test x"$samba_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
+ AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Whether there is a C99 compliant vsnprintf])
+fi
+
+
+dnl VA_COPY
+AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[
+AC_TRY_LINK([#include <stdarg.h>
+va_list ap1,ap2;], [va_copy(ap1,ap2);],
+samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)])
+if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then
+ AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available])
+fi
+
+if test x"$samba_cv_HAVE_VA_COPY" != x"yes"; then
+AC_CACHE_CHECK([for __va_copy],samba_cv_HAVE___VA_COPY,[
+AC_TRY_LINK([#include <stdarg.h>
+va_list ap1,ap2;], [__va_copy(ap1,ap2);],
+samba_cv_HAVE___VA_COPY=yes,samba_cv_HAVE___VA_COPY=no)])
+if test x"$samba_cv_HAVE___VA_COPY" = x"yes"; then
+ AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available])
+fi
+fi
+
+dnl __FUNCTION__ macro
+AC_CACHE_CHECK([for __FUNCTION__ macro],samba_cv_HAVE_FUNCTION_MACRO,[
+AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __FUNCTION__);],
+samba_cv_HAVE_FUNCTION_MACRO=yes,samba_cv_HAVE_FUNCTION_MACRO=no)])
+if test x"$samba_cv_HAVE_FUNCTION_MACRO" = x"yes"; then
+ AC_DEFINE(HAVE_FUNCTION_MACRO,1,[Whether there is a __FUNCTION__ macro])
+else
+ dnl __func__ macro
+ AC_CACHE_CHECK([for __func__ macro],samba_cv_HAVE_func_MACRO,[
+ AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);],
+ samba_cv_HAVE_func_MACRO=yes,samba_cv_HAVE_func_MACRO=no)])
+ if test x"$samba_cv_HAVE_func_MACRO" = x"yes"; then
+ AC_DEFINE(HAVE_func_MACRO,1,[Whether there is a __func__ macro])
+ fi
+fi
+
+AC_CHECK_HEADERS([sys/param.h limits.h])
+
+AC_CHECK_TYPE(comparison_fn_t,
+[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
+
+AC_CHECK_FUNCS(strnlen setenv)
+AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq)
+
+# this test disabled as we don't actually need __VA_ARGS__ yet
+AC_TRY_CPP([
+#define eprintf(...) fprintf(stderr, __VA_ARGS__)
+eprintf("bla", "bar");
+], AC_DEFINE(HAVE__VA_ARGS__MACRO, 1, [Whether the __VA_ARGS__ macro is available]))
+
+# Check prerequisites
+AC_CHECK_FUNCS([memset printf syslog], [],
+ [ AC_MSG_ERROR([Required function not found])])
+
+AC_CACHE_CHECK([for sig_atomic_t type],samba_cv_sig_atomic_t, [
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <signal.h>],[sig_atomic_t i = 0],
+ samba_cv_sig_atomic_t=yes,samba_cv_sig_atomic_t=no)])
+if test x"$samba_cv_sig_atomic_t" = x"yes"; then
+ AC_DEFINE(HAVE_SIG_ATOMIC_T_TYPE,1,[Whether we have the atomic_t variable type])
+fi
+
+
+AC_CACHE_CHECK([for O_DIRECT flag to open(2)],samba_cv_HAVE_OPEN_O_DIRECT,[
+AC_TRY_COMPILE([
+#include <unistd.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif],
+[int fd = open("/dev/null", O_DIRECT);],
+samba_cv_HAVE_OPEN_O_DIRECT=yes,samba_cv_HAVE_OPEN_O_DIRECT=no)])
+if test x"$samba_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then
+ AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT])
+fi
+
+
+AC_CACHE_CHECK([that the C compiler can precompile header files],samba_cv_precompiled_headers, [
+ dnl Check whether the compiler can generate precompiled headers
+ touch conftest.h
+ if ${CC-cc} conftest.h 2> /dev/null && test -f conftest.h.gch; then
+ precompiled_headers=yes
+ else
+ precompiled_headers=no
+ fi])
+AC_SUBST(precompiled_headers)
+
+
+dnl Check if the C compiler understands volatile (it should, being ANSI).
+AC_CACHE_CHECK([that the C compiler understands volatile],samba_cv_volatile, [
+ AC_TRY_COMPILE([#include <sys/types.h>],[volatile int i = 0],
+ samba_cv_volatile=yes,samba_cv_volatile=no)])
+if test x"$samba_cv_volatile" = x"yes"; then
+ AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile])
+fi
+
+m4_include(system/config.m4)
+
+m4_include(dlfcn.m4)
+m4_include(getpass.m4)
+m4_include(win32.m4)
+m4_include(timegm.m4)
+m4_include(repdir.m4)
+
+AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent memcpy],,
+ [AC_MSG_ERROR([Required function not found])])
+
+echo "LIBREPLACE_BROKEN_CHECKS: END"
+]) dnl end AC_LIBREPLACE_BROKEN_CHECKS
+
+AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_START,
+[
+#LIBREPLACE_ALL_CHECKS: START"
+])
+AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_END,
+[
+#LIBREPLACE_ALL_CHECKS: END"
+])
+m4_define(AC_LIBREPLACE_ALL_CHECKS,
+[
+AC__LIBREPLACE_ALL_CHECKS_START
+AC_LIBREPLACE_LOCATION_CHECKS
+AC_LIBREPLACE_CC_CHECKS
+AC_LIBREPLACE_BROKEN_CHECKS
+AC__LIBREPLACE_ALL_CHECKS_END
+])
+
+m4_include(libreplace_cc.m4)
+m4_include(libreplace_macros.m4)
+m4_include(autoconf-2.60.m4)
diff --git a/source/lib/replace/libreplace_cc.m4 b/source/lib/replace/libreplace_cc.m4
new file mode 100644
index 00000000000..74c53cad998
--- /dev/null
+++ b/source/lib/replace/libreplace_cc.m4
@@ -0,0 +1,167 @@
+
+AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_START,
+[
+echo "LIBREPLACE_CC_CHECKS: START"
+])
+
+AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_END,
+[
+echo "LIBREPLACE_CC_CHECKS: END"
+])
+
+dnl
+dnl
+dnl AC_LIBREPLACE_CC_CHECKS
+dnl
+dnl Note: we need to use m4_define instead of AC_DEFUN because
+dnl of the ordering of tests
+dnl
+dnl
+m4_define(AC_LIBREPLACE_CC_CHECKS,
+[
+AC__LIBREPLACE_ONLY_CC_CHECKS_START
+
+dnl stop the C89 attempt by autoconf - if autoconf detects -Ae it will enable it
+dnl which conflicts with C99 on HPUX
+ac_cv_prog_cc_Ae=no
+
+savedCFLAGS=$CFLAGS
+AC_PROG_CC
+CFLAGS=$savedCFLAGS
+
+dnl don't try for C99 if we are using gcc, as otherwise we
+dnl lose immediate structure constants
+if test x"$GCC" != x"yes" ; then
+AC_PROG_CC_C99
+fi
+
+if test x"$GCC" = x"yes" ; then
+ AC_MSG_CHECKING([for version of gcc])
+ GCC_VERSION=`$CC -dumpversion`
+ AC_MSG_RESULT(${GCC_VERSION})
+fi
+AC_USE_SYSTEM_EXTENSIONS
+AC_C_BIGENDIAN
+AC_C_INLINE
+LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_WARN([c99 structure initializer are not supported])])
+
+AC_PROG_INSTALL
+
+AC_ISC_POSIX
+AC_EXTENSION_FLAG(_XOPEN_SOURCE_EXTENDED)
+AC_EXTENSION_FLAG(_OSF_SOURCE)
+
+AC_SYS_LARGEFILE
+
+dnl Add #include for broken IRIX header files
+case "$host_os" in
+ *irix6*) AC_ADD_INCLUDE(<standards.h>)
+ ;;
+ *hpux*)
+ # mmap on HPUX is completely broken...
+ AC_DEFINE(MMAP_BLACKLIST, 1, [Whether MMAP is broken])
+ if test "`uname -r`" = "B.11.11"; then
+ AC_MSG_WARN([Enabling HPUX 11.11 header bug workaround])
+ CFLAGS="$CFLAGS -D_LARGEFILE64_SUPPORT -D__LP64__ -DO_LARGEFILE=04000"
+ fi
+ if test "`uname -r`" = "B.11.23"; then
+ AC_MSG_WARN([Enabling HPUX 11.23 machine/sys/getppdp.h bug workaround])
+ CFLAGS="$CFLAGS -D_MACHINE_SYS_GETPPDP_INCLUDED"
+ fi
+ ;;
+ *aix*)
+ AC_DEFINE(BROKEN_STRNDUP, 1, [Whether strndup is broken])
+ AC_DEFINE(BROKEN_STRNLEN, 1, [Whether strnlen is broken])
+ if test "${GCC}" != "yes"; then
+ ## for funky AIX compiler using strncpy()
+ CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
+ fi
+ ;;
+ #
+ # VOS may need to have POSIX support and System V compatibility enabled.
+ #
+ *vos*)
+ case "$CFLAGS" in
+ *-D_POSIX_C_SOURCE*);;
+ *)
+ CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112L"
+ AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Whether to enable POSIX support])
+ ;;
+ esac
+ case "$CFLAGS" in
+ *-D_SYSV*|*-D_SVID_SOURCE*);;
+ *)
+ CFLAGS="$CFLAGS -D_SYSV"
+ AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility])
+ ;;
+ esac
+ ;;
+esac
+
+
+
+AC_CHECK_HEADERS([standards.h])
+
+# Solaris needs HAVE_LONG_LONG defined
+AC_CHECK_TYPES(long long)
+
+AC_CHECK_TYPE(uint_t, unsigned int)
+AC_CHECK_TYPE(int8_t, char)
+AC_CHECK_TYPE(uint8_t, unsigned char)
+AC_CHECK_TYPE(int16_t, short)
+AC_CHECK_TYPE(uint16_t, unsigned short)
+AC_CHECK_TYPE(int32_t, long)
+AC_CHECK_TYPE(uint32_t, unsigned long)
+AC_CHECK_TYPE(int64_t, long long)
+AC_CHECK_TYPE(uint64_t, unsigned long long)
+
+AC_CHECK_TYPE(size_t, unsigned int)
+AC_CHECK_TYPE(ssize_t, int)
+
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(char)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(long long)
+
+AC_CHECK_SIZEOF(off_t)
+AC_CHECK_SIZEOF(size_t)
+AC_CHECK_SIZEOF(ssize_t)
+
+AC_CHECK_TYPE(intptr_t, unsigned long long)
+AC_CHECK_TYPE(ptrdiff_t, unsigned long long)
+
+if test x"$ac_cv_type_long_long" != x"yes";then
+ AC_MSG_ERROR([LIBREPLACE needs type 'long long'])
+fi
+if test $ac_cv_sizeof_long_long -lt 8;then
+ AC_MSG_ERROR([LIBREPLACE needs sizeof(long long) >= 8])
+fi
+
+############################################
+# check if the compiler can do immediate structures
+AC_SUBST(libreplace_cv_immediate_structures)
+AC_CACHE_CHECK([for immediate structures],libreplace_cv_immediate_structures,[
+ AC_TRY_COMPILE([
+ #include <stdio.h>
+ ],[
+ typedef struct {unsigned x;} FOOBAR;
+ #define X_FOOBAR(x) ((FOOBAR) { x })
+ #define FOO_ONE X_FOOBAR(1)
+ FOOBAR f = FOO_ONE;
+ static const struct {
+ FOOBAR y;
+ } f2[] = {
+ {FOO_ONE}
+ };
+ ],
+ libreplace_cv_immediate_structures=yes,
+ libreplace_cv_immediate_structures=no,
+ libreplace_cv_immediate_structures=cross)
+])
+if test x"$libreplace_cv_immediate_structures" = x"yes"; then
+ AC_DEFINE(HAVE_IMMEDIATE_STRUCTURES,1,[Whether the compiler supports immediate structures])
+fi
+
+AC__LIBREPLACE_ONLY_CC_CHECKS_END
+]) dnl end AC_LIBREPLACE_CC_CHECKS
diff --git a/source/lib/replace/libreplace_macros.m4 b/source/lib/replace/libreplace_macros.m4
new file mode 100644
index 00000000000..0669c10c2a0
--- /dev/null
+++ b/source/lib/replace/libreplace_macros.m4
@@ -0,0 +1,308 @@
+#
+# This is a collection of useful autoconf macros
+#
+
+############################################
+# Check if the compiler handles c99 struct initialization, and if not try -AC99 and -c99 flags
+# Usage: LIBREPLACE_C99_STRUCT_INIT(success-action,failure-action)
+# changes CFLAGS to add -AC99 or -c99 if needed
+AC_DEFUN([LIBREPLACE_C99_STRUCT_INIT],
+[
+saved_CFLAGS="$CFLAGS";
+c99_init=no
+if test x"$c99_init" = x"no"; then
+ AC_MSG_CHECKING(for C99 designated initializers)
+ CFLAGS="$saved_CFLAGS";
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [ struct foo {int x;char y;};
+ struct foo bar = { .y = 'X', .x = 1 };
+ ],
+ [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)])
+fi
+if test x"$c99_init" = x"no"; then
+ AC_MSG_CHECKING(for C99 designated initializers with -AC99)
+ CFLAGS="$saved_CFLAGS -AC99";
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [ struct foo {int x;char y;};
+ struct foo bar = { .y = 'X', .x = 1 };
+ ],
+ [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)])
+fi
+if test x"$c99_init" = x"no"; then
+ AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=extc99)
+ CFLAGS="$saved_CFLAGS -qlanglvl=extc99";
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [ struct foo {int x;char y;};
+ struct foo bar = { .y = 'X', .x = 1 };
+ ],
+ [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)])
+fi
+if test x"$c99_init" = x"no"; then
+ AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=stdc99)
+ CFLAGS="$saved_CFLAGS -qlanglvl=stdc99";
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [ struct foo {int x;char y;};
+ struct foo bar = { .y = 'X', .x = 1 };
+ ],
+ [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)])
+fi
+if test x"$c99_init" = x"no"; then
+ AC_MSG_CHECKING(for C99 designated initializers with -c99)
+ CFLAGS="$saved_CFLAGS -c99"
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [ struct foo {int x;char y;};
+ struct foo bar = { .y = 'X', .x = 1 };
+ ],
+ [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)])
+fi
+
+if test "`uname`" = "HP-UX"; then
+ if test "$ac_cv_c_compiler_gnu" = no; then
+ # special override for broken HP-UX compiler - I can't find a way to test
+ # this properly (its a compiler bug)
+ CFLAGS="$CFLAGS -AC99";
+ c99_init=yes;
+ fi
+fi
+
+if test x"$c99_init" = x"yes"; then
+ saved_CFLAGS=""
+ $1
+else
+ CFLAGS="$saved_CFLAGS"
+ saved_CFLAGS=""
+ $2
+fi
+])
+
+dnl AC_PROG_CC_FLAG(flag)
+AC_DEFUN(AC_PROG_CC_FLAG,
+[AC_CACHE_CHECK(whether ${CC-cc} accepts -$1, ac_cv_prog_cc_$1,
+[echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -$1 -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_$1=yes
+else
+ ac_cv_prog_cc_$1=no
+fi
+rm -f conftest*
+])])
+
+AC_DEFUN([AC_EXTENSION_FLAG],
+[
+ cat >>confdefs.h <<\EOF
+#ifndef $1
+# define $1 1
+#endif
+EOF
+AH_VERBATIM([$1], [#ifndef $1
+# define $1 1
+#endif])
+])
+
+
+dnl see if a declaration exists for a function or variable
+dnl defines HAVE_function_DECL if it exists
+dnl AC_HAVE_DECL(var, includes)
+AC_DEFUN(AC_HAVE_DECL,
+[
+ AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[
+ AC_TRY_COMPILE([$2],[int i = (int)$1],
+ ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)])
+ if test x"$ac_cv_have_$1_decl" = x"yes"; then
+ AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available])
+ fi
+])
+
+
+# AC_CHECK_LIB_EXT(LIBRARY, [EXT_LIBS], [FUNCTION],
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],
+# [ADD-ACTION-IF-FOUND],[OTHER-LIBRARIES])
+# ------------------------------------------------------
+#
+# Use a cache variable name containing both the library and function name,
+# because the test really is for library $1 defining function $3, not
+# just for library $1. Separate tests with the same $1 and different $3s
+# may have different results.
+#
+# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$3])
+# is asking for trouble, since AC_CHECK_LIB($lib, fun) would give
+# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence
+# the AS_LITERAL_IF indirection.
+#
+# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally,
+# whatever the FUNCTION, in addition to not being a *S macro. Note
+# that the cache does depend upon the function we are looking for.
+#
+# It is on purpose we used `ac_check_lib_ext_save_LIBS' and not just
+# `ac_save_LIBS': there are many macros which don't want to see `LIBS'
+# changed but still want to use AC_CHECK_LIB_EXT, so they save `LIBS'.
+# And ``ac_save_LIBS' is too tempting a name, so let's leave them some
+# freedom.
+AC_DEFUN([AC_CHECK_LIB_EXT],
+[
+AH_CHECK_LIB_EXT([$1])
+ac_check_lib_ext_save_LIBS=$LIBS
+LIBS="-l$1 $$2 $7 $LIBS"
+AS_LITERAL_IF([$1],
+ [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1])],
+ [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1''])])dnl
+
+m4_ifval([$3],
+ [
+ AH_CHECK_FUNC_EXT([$3])
+ AS_LITERAL_IF([$1],
+ [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1_$3])],
+ [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1''_$3])])dnl
+ AC_CACHE_CHECK([for $3 in -l$1], ac_Lib_func,
+ [AC_TRY_LINK_FUNC($3,
+ [AS_VAR_SET(ac_Lib_func, yes);
+ AS_VAR_SET(ac_Lib_ext, yes)],
+ [AS_VAR_SET(ac_Lib_func, no);
+ AS_VAR_SET(ac_Lib_ext, no)])
+ ])
+ AS_IF([test AS_VAR_GET(ac_Lib_func) = yes],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$3))])dnl
+ AS_VAR_POPDEF([ac_Lib_func])dnl
+ ],[
+ AC_CACHE_CHECK([for -l$1], ac_Lib_ext,
+ [AC_TRY_LINK_FUNC([main],
+ [AS_VAR_SET(ac_Lib_ext, yes)],
+ [AS_VAR_SET(ac_Lib_ext, no)])
+ ])
+ ])
+LIBS=$ac_check_lib_ext_save_LIBS
+
+AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes],
+ [m4_default([$4],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1))
+ case "$$2" in
+ *-l$1*)
+ ;;
+ *)
+ $2="-l$1 $$2"
+ ;;
+ esac])
+ [$6]
+ ],
+ [$5])dnl
+AS_VAR_POPDEF([ac_Lib_ext])dnl
+])# AC_CHECK_LIB_EXT
+
+# AH_CHECK_LIB_EXT(LIBNAME)
+# ---------------------
+m4_define([AH_CHECK_LIB_EXT],
+[AH_TEMPLATE(AS_TR_CPP(HAVE_LIB$1),
+ [Define to 1 if you have the `]$1[' library (-l]$1[).])])
+
+dnl AC_SEARCH_LIBS_EXT(FUNCTION, SEARCH-LIBS, EXT_LIBS,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],
+dnl [OTHER-LIBRARIES])
+dnl --------------------------------------------------------
+dnl Search for a library defining FUNC, if it's not already available.
+AC_DEFUN([AC_SEARCH_LIBS_EXT],
+[AC_CACHE_CHECK([for library containing $1], [ac_cv_search_ext_$1],
+[
+ac_func_search_ext_save_LIBS=$LIBS
+ac_cv_search_ext_$1=no
+AC_LINK_IFELSE([AC_LANG_CALL([], [$1])],
+ [ac_cv_search_ext_$1="none required"])
+if test "$ac_cv_search_ext_$1" = no; then
+ for ac_lib in $2; do
+ LIBS="-l$ac_lib $$3 $6 $ac_func_search_save_ext_LIBS"
+ AC_LINK_IFELSE([AC_LANG_CALL([], [$1])],
+ [ac_cv_search_ext_$1="-l$ac_lib"
+break])
+ done
+fi
+LIBS=$ac_func_search_ext_save_LIBS])
+AS_IF([test "$ac_cv_search_ext_$1" != no],
+ [test "$ac_cv_search_ext_$1" = "none required" || $3="$ac_cv_search_ext_$1 $$3"
+ $4],
+ [$5])dnl
+])
+
+dnl check for a function in a $LIBS and $OTHER_LIBS libraries variable.
+dnl AC_CHECK_FUNC_EXT(func,OTHER_LIBS,IF-TRUE,IF-FALSE)
+AC_DEFUN([AC_CHECK_FUNC_EXT],
+[
+ AH_CHECK_FUNC_EXT($1)
+ ac_check_func_ext_save_LIBS=$LIBS
+ LIBS="$2 $LIBS"
+ AS_VAR_PUSHDEF([ac_var], [ac_cv_func_ext_$1])dnl
+ AC_CACHE_CHECK([for $1], ac_var,
+ [AC_LINK_IFELSE([AC_LANG_FUNC_LINK_TRY([$1])],
+ [AS_VAR_SET(ac_var, yes)],
+ [AS_VAR_SET(ac_var, no)])])
+ LIBS=$ac_check_func_ext_save_LIBS
+ AS_IF([test AS_VAR_GET(ac_var) = yes],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1])) $3],
+ [$4])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])# AC_CHECK_FUNC
+
+# AH_CHECK_FUNC_EXT(FUNCNAME)
+# ---------------------
+m4_define([AH_CHECK_FUNC_EXT],
+[AH_TEMPLATE(AS_TR_CPP(HAVE_$1),
+ [Define to 1 if you have the `]$1[' function.])])
+
+dnl Define an AC_DEFINE with ifndef guard.
+dnl AC_N_DEFINE(VARIABLE [, VALUE])
+define(AC_N_DEFINE,
+[cat >> confdefs.h <<\EOF
+[#ifndef] $1
+[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1)
+[#endif]
+EOF
+])
+
+dnl Add an #include
+dnl AC_ADD_INCLUDE(VARIABLE)
+define(AC_ADD_INCLUDE,
+[cat >> confdefs.h <<\EOF
+[#include] $1
+EOF
+])
+
+dnl remove an #include
+dnl AC_REMOVE_INCLUDE(VARIABLE)
+define(AC_REMOVE_INCLUDE,
+[
+grep -v '[#include] $1' confdefs.h >confdefs.h.tmp
+cat confdefs.h.tmp > confdefs.h
+rm confdefs.h.tmp
+])
+
+dnl remove an #define
+dnl AC_REMOVE_DEFINE(VARIABLE)
+define(AC_REMOVE_DEFINE,
+[
+grep -v '[#define] $1 ' confdefs.h |grep -v '[#define] $1[$]'>confdefs.h.tmp
+cat confdefs.h.tmp > confdefs.h
+rm confdefs.h.tmp
+])
+
+dnl AS_HELP_STRING is not available in autoconf 2.57, and AC_HELP_STRING is deprecated
+dnl in autoconf 2.59, so define AS_HELP_STRING to be AC_HELP_STRING unless it is already
+dnl defined.
+m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))])
+
+dnl check if the prototype in the header matches the given one
+dnl AC_VERIFY_C_PROTOTYPE(prototype,functionbody,[IF-TRUE].[IF-FALSE],[extraheaders])
+AC_DEFUN(AC_VERIFY_C_PROTOTYPE,
+[AC_CACHE_CHECK([for prototype $1], AS_TR_SH([ac_cv_c_prototype_$1]),
+ AC_COMPILE_IFELSE([
+ AC_INCLUDES_DEFAULT
+ $5
+ $1
+ {
+ $2
+ }
+ ],[
+ AS_TR_SH([ac_cv_c_prototype_$1])=yes
+ ],[
+ AS_TR_SH([ac_cv_c_prototype_$1])=no
+ ])
+)
+AS_IF([test $AS_TR_SH([ac_cv_c_prototype_$1]) = yes],[$3],[$4])
+])
diff --git a/source/lib/replace/repdir.m4 b/source/lib/replace/repdir.m4
new file mode 100644
index 00000000000..f53a4c29745
--- /dev/null
+++ b/source/lib/replace/repdir.m4
@@ -0,0 +1,78 @@
+AC_CACHE_CHECK([for broken readdir],libreplace_cv_READDIR_NEEDED,[
+ AC_TRY_RUN([
+#define test_readdir_os2_delete main
+#include "$libreplacedir/test/os2_delete.c"],
+ [libreplace_cv_READDIR_NEEDED=no],
+ [libreplace_cv_READDIR_NEEDED=yes],
+ [libreplace_cv_READDIR_NEEDED="assuming not"])
+])
+
+#
+# try to replace with getdirentries() if needed
+#
+if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then
+AC_CHECK_FUNCS(getdirentries)
+AC_VERIFY_C_PROTOTYPE([long telldir(const DIR *dir)],
+ [
+ return 0;
+ ],[
+ AC_DEFINE(TELLDIR_TAKES_CONST_DIR, 1, [Whether telldir takes a const pointer])
+ ],[],[
+ #include <dirent.h>
+ ])
+
+AC_VERIFY_C_PROTOTYPE([int seekdir(DIR *dir, long ofs)],
+ [
+ return 0;
+ ],[
+ AC_DEFINE(SEEKDIR_RETURNS_INT, 1, [Whether seekdir returns an int])
+ ],[],[
+ #include <dirent.h>
+ ])
+AC_CACHE_CHECK([for replacing readdir using getdirentries()],libreplace_cv_READDIR_GETDIRENTRIES,[
+ AC_TRY_RUN([
+#define _LIBREPLACE_REPLACE_H
+#include "$libreplacedir/repdir_getdirentries.c"
+#define test_readdir_os2_delete main
+#include "$libreplacedir/test/os2_delete.c"],
+ [libreplace_cv_READDIR_GETDIRENTRIES=yes],
+ [libreplace_cv_READDIR_GETDIRENTRIES=no])
+])
+fi
+if test x"$libreplace_cv_READDIR_GETDIRENTRIES" = x"yes"; then
+ AC_DEFINE(REPLACE_READDIR,1,[replace readdir])
+ AC_DEFINE(REPLACE_READDIR_GETDIRENTRIES,1,[replace readdir using getdirentries()])
+ LIBREPLACEOBJ="${LIBREPLACEOBJ} repdir_getdirentries.o"
+ libreplace_cv_READDIR_NEEDED=no
+fi
+
+#
+# try to replace with getdents() if needed
+#
+if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then
+AC_CHECK_FUNCS(getdents)
+AC_CACHE_CHECK([for replacing readdir using getdents()],libreplace_cv_READDIR_GETDENTS,[
+ AC_TRY_RUN([
+#define _LIBREPLACE_REPLACE_H
+#error _donot_use_getdents_replacement_anymore
+#include "$libreplacedir/repdir_getdents.c"
+#define test_readdir_os2_delete main
+#include "$libreplacedir/test/os2_delete.c"],
+ [libreplace_cv_READDIR_GETDENTS=yes],
+ [libreplace_cv_READDIR_GETDENTS=no])
+])
+fi
+if test x"$libreplace_cv_READDIR_GETDENTS" = x"yes"; then
+ AC_DEFINE(REPLACE_READDIR,1,[replace readdir])
+ AC_DEFINE(REPLACE_READDIR_GETDENTS,1,[replace readdir using getdents()])
+ LIBREPLACEOBJ="${LIBREPLACEOBJ} repdir_getdents.o"
+ libreplace_cv_READDIR_NEEDED=no
+fi
+
+AC_MSG_CHECKING([a usable readdir()])
+if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then
+ AC_MSG_RESULT(no)
+ AC_MSG_WARN([the provided readdir() is broken])
+else
+ AC_MSG_RESULT(yes)
+fi
diff --git a/source/lib/replace/repdir_getdents.c b/source/lib/replace/repdir_getdents.c
new file mode 100644
index 00000000000..6b115c4c4fb
--- /dev/null
+++ b/source/lib/replace/repdir_getdents.c
@@ -0,0 +1,167 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2005
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ a replacement for opendir/readdir/telldir/seekdir/closedir for BSD systems
+
+ This is needed because the existing directory handling in FreeBSD
+ and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink()
+ on files in a directory where telldir() has been used. On a block
+ boundary it will occasionally miss a file when seekdir() is used to
+ return to a position previously recorded with telldir().
+
+ This also fixes a severe performance and memory usage problem with
+ telldir() on BSD systems. Each call to telldir() in BSD adds an
+ entry to a linked list, and those entries are cleaned up on
+ closedir(). This means with a large directory closedir() can take an
+ arbitrary amount of time, causing network timeouts as millions of
+ telldir() entries are freed
+
+ Note! This replacement code is not portable. It relies on getdents()
+ always leaving the file descriptor at a seek offset that is a
+ multiple of DIR_BUF_SIZE. If the code detects that this doesn't
+ happen then it will abort(). It also does not handle directories
+ with offsets larger than can be stored in a long,
+
+ This code is available under other free software licenses as
+ well. Contact the author.
+*/
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define DIR_BUF_BITS 9
+#define DIR_BUF_SIZE (1<<DIR_BUF_BITS)
+
+struct dir_buf {
+ int fd;
+ int nbytes, ofs;
+ off_t seekpos;
+ char buf[DIR_BUF_SIZE];
+};
+
+DIR *opendir(const char *dname)
+{
+ struct dir_buf *d;
+ struct stat sb;
+ d = malloc(sizeof(*d));
+ if (d == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ d->fd = open(dname, O_RDONLY);
+ if (d->fd == -1) {
+ free(d);
+ return NULL;
+ }
+ if (fstat(d->fd, &sb) < 0) {
+ close(d->fd);
+ free(d);
+ return NULL;
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ close(d->fd);
+ free(d);
+ errno = ENOTDIR;
+ return NULL;
+ }
+ d->ofs = 0;
+ d->seekpos = 0;
+ d->nbytes = 0;
+ return (DIR *)d;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ struct dirent *de;
+
+ if (d->ofs >= d->nbytes) {
+ d->seekpos = lseek(d->fd, 0, SEEK_CUR);
+ d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE);
+ d->ofs = 0;
+ }
+ if (d->ofs >= d->nbytes) {
+ return NULL;
+ }
+ de = (struct dirent *)&d->buf[d->ofs];
+ d->ofs += de->d_reclen;
+ return de;
+}
+
+long telldir(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ if (d->ofs >= d->nbytes) {
+ d->seekpos = lseek(d->fd, 0, SEEK_CUR);
+ d->ofs = 0;
+ d->nbytes = 0;
+ }
+ /* this relies on seekpos always being a multiple of
+ DIR_BUF_SIZE. Is that always true on BSD systems? */
+ if (d->seekpos & (DIR_BUF_SIZE-1)) {
+ abort();
+ }
+ return d->seekpos + d->ofs;
+}
+
+void seekdir(DIR *dir, long ofs)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET);
+ d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE);
+ d->ofs = 0;
+ while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) {
+ if (readdir(dir) == NULL) break;
+ }
+}
+
+void rewinddir(DIR *dir)
+{
+ seekdir(dir, 0);
+}
+
+int closedir(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ int r = close(d->fd);
+ if (r != 0) {
+ return r;
+ }
+ free(d);
+ return 0;
+}
+
+#ifndef dirfd
+/* darn, this is a macro on some systems. */
+int dirfd(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ return d->fd;
+}
+#endif
diff --git a/source/lib/replace/repdir_getdirentries.c b/source/lib/replace/repdir_getdirentries.c
new file mode 100644
index 00000000000..a6026dfb5d4
--- /dev/null
+++ b/source/lib/replace/repdir_getdirentries.c
@@ -0,0 +1,184 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2005
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ a replacement for opendir/readdir/telldir/seekdir/closedir for BSD
+ systems using getdirentries
+
+ This is needed because the existing directory handling in FreeBSD
+ and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink()
+ on files in a directory where telldir() has been used. On a block
+ boundary it will occasionally miss a file when seekdir() is used to
+ return to a position previously recorded with telldir().
+
+ This also fixes a severe performance and memory usage problem with
+ telldir() on BSD systems. Each call to telldir() in BSD adds an
+ entry to a linked list, and those entries are cleaned up on
+ closedir(). This means with a large directory closedir() can take an
+ arbitrary amount of time, causing network timeouts as millions of
+ telldir() entries are freed
+
+ Note! This replacement code is not portable. It relies on
+ getdirentries() always leaving the file descriptor at a seek offset
+ that is a multiple of DIR_BUF_SIZE. If the code detects that this
+ doesn't happen then it will abort(). It also does not handle
+ directories with offsets larger than can be stored in a long,
+
+ This code is available under other free software licenses as
+ well. Contact the author.
+*/
+
+#include "replace.h"
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define DIR_BUF_BITS 9
+#define DIR_BUF_SIZE (1<<DIR_BUF_BITS)
+
+struct dir_buf {
+ int fd;
+ int nbytes, ofs;
+ off_t seekpos;
+ char buf[DIR_BUF_SIZE];
+};
+
+DIR *opendir(const char *dname)
+{
+ struct dir_buf *d;
+ struct stat sb;
+ d = malloc(sizeof(*d));
+ if (d == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ d->fd = open(dname, O_RDONLY);
+ if (d->fd == -1) {
+ free(d);
+ return NULL;
+ }
+ if (fstat(d->fd, &sb) < 0) {
+ close(d->fd);
+ free(d);
+ return NULL;
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ close(d->fd);
+ free(d);
+ errno = ENOTDIR;
+ return NULL;
+ }
+ d->ofs = 0;
+ d->seekpos = 0;
+ d->nbytes = 0;
+ return (DIR *)d;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ struct dirent *de;
+
+ if (d->ofs >= d->nbytes) {
+ long pos;
+ d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos);
+ d->seekpos = pos;
+ d->ofs = 0;
+ }
+ if (d->ofs >= d->nbytes) {
+ return NULL;
+ }
+ de = (struct dirent *)&d->buf[d->ofs];
+ d->ofs += de->d_reclen;
+ return de;
+}
+
+#ifdef TELLDIR_TAKES_CONST_DIR
+long telldir(const DIR *dir)
+#else
+long telldir(DIR *dir)
+#endif
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ if (d->ofs >= d->nbytes) {
+ d->seekpos = lseek(d->fd, 0, SEEK_CUR);
+ d->ofs = 0;
+ d->nbytes = 0;
+ }
+ /* this relies on seekpos always being a multiple of
+ DIR_BUF_SIZE. Is that always true on BSD systems? */
+ if (d->seekpos & (DIR_BUF_SIZE-1)) {
+ abort();
+ }
+ return d->seekpos + d->ofs;
+}
+
+#ifdef SEEKDIR_RETURNS_INT
+int seekdir(DIR *dir, long ofs)
+#else
+void seekdir(DIR *dir, long ofs)
+#endif
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ long pos;
+ d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET);
+ d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos);
+ d->ofs = 0;
+ while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) {
+ if (readdir(dir) == NULL) break;
+ }
+#ifdef SEEKDIR_RETURNS_INT
+ return -1;
+#endif
+}
+
+void rewinddir(DIR *dir)
+{
+ seekdir(dir, 0);
+}
+
+int closedir(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ int r = close(d->fd);
+ if (r != 0) {
+ return r;
+ }
+ free(d);
+ return 0;
+}
+
+#ifndef dirfd
+/* darn, this is a macro on some systems. */
+int dirfd(DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ return d->fd;
+}
+#endif
+
+
diff --git a/source/lib/replace/replace.c b/source/lib/replace/replace.c
new file mode 100644
index 00000000000..9e6c75bd358
--- /dev/null
+++ b/source/lib/replace/replace.c
@@ -0,0 +1,613 @@
+/*
+ Unix SMB/CIFS implementation.
+ replacement routines for broken systems
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "replace.h"
+
+#include "system/filesys.h"
+#include "system/time.h"
+#include "system/passwd.h"
+#include "system/syslog.h"
+#include "system/network.h"
+#include "system/locale.h"
+#include "system/wait.h"
+
+void replace_dummy(void);
+void replace_dummy(void) {}
+
+#ifndef HAVE_FTRUNCATE
+ /*******************************************************************
+ftruncate for operating systems that don't have it
+********************************************************************/
+int rep_ftruncate(int f, off_t l)
+{
+#ifdef HAVE_CHSIZE
+ return chsize(f,l);
+#elif defined(F_FREESP)
+ struct flock fl;
+
+ fl.l_whence = 0;
+ fl.l_len = 0;
+ fl.l_start = l;
+ fl.l_type = F_WRLCK;
+ return fcntl(f, F_FREESP, &fl);
+#else
+#error "you must have a ftruncate function"
+#endif
+}
+#endif /* HAVE_FTRUNCATE */
+
+
+#ifndef HAVE_STRLCPY
+/* like strncpy but does not 0 fill the buffer and always null
+ terminates. bufsize is the size of the destination buffer */
+size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
+{
+ size_t len = strlen(s);
+ size_t ret = len;
+ if (bufsize <= 0) return 0;
+ if (len >= bufsize) len = bufsize-1;
+ memcpy(d, s, len);
+ d[len] = 0;
+ return ret;
+}
+#endif
+
+#ifndef HAVE_STRLCAT
+/* like strncat but does not 0 fill the buffer and always null
+ terminates. bufsize is the length of the buffer, which should
+ be one more than the maximum resulting string length */
+size_t rep_strlcat(char *d, const char *s, size_t bufsize)
+{
+ size_t len1 = strlen(d);
+ size_t len2 = strlen(s);
+ size_t ret = len1 + len2;
+
+ if (len1+len2 >= bufsize) {
+ len2 = bufsize - (len1+1);
+ }
+ if (len2 > 0) {
+ memcpy(d+len1, s, len2);
+ d[len1+len2] = 0;
+ }
+ return ret;
+}
+#endif
+
+#ifndef HAVE_MKTIME
+/*******************************************************************
+a mktime() replacement for those who don't have it - contributed by
+C.A. Lademann <cal@zls.com>
+Corrections by richard.kettlewell@kewill.com
+********************************************************************/
+
+#define MINUTE 60
+#define HOUR 60*MINUTE
+#define DAY 24*HOUR
+#define YEAR 365*DAY
+time_t rep_mktime(struct tm *t)
+{
+ struct tm *u;
+ time_t epoch = 0;
+ int n;
+ int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ y, m, i;
+
+ if(t->tm_year < 70)
+ return((time_t)-1);
+
+ n = t->tm_year + 1900 - 1;
+ epoch = (t->tm_year - 70) * YEAR +
+ ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
+
+ y = t->tm_year + 1900;
+ m = 0;
+
+ for(i = 0; i < t->tm_mon; i++) {
+ epoch += mon [m] * DAY;
+ if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
+ epoch += DAY;
+
+ if(++m > 11) {
+ m = 0;
+ y++;
+ }
+ }
+
+ epoch += (t->tm_mday - 1) * DAY;
+ epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
+
+ if((u = localtime(&epoch)) != NULL) {
+ t->tm_sec = u->tm_sec;
+ t->tm_min = u->tm_min;
+ t->tm_hour = u->tm_hour;
+ t->tm_mday = u->tm_mday;
+ t->tm_mon = u->tm_mon;
+ t->tm_year = u->tm_year;
+ t->tm_wday = u->tm_wday;
+ t->tm_yday = u->tm_yday;
+ t->tm_isdst = u->tm_isdst;
+ }
+
+ return(epoch);
+}
+#endif /* !HAVE_MKTIME */
+
+
+#ifndef HAVE_INNETGR
+#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
+/*
+ * Search for a match in a netgroup. This replaces it on broken systems.
+ */
+int rep_innetgr(const char *group, const char *host, const char *user,
+ const char *dom)
+{
+ char *hst, *usr, *dm;
+
+ setnetgrent(group);
+ while (getnetgrent(&hst, &usr, &dm)) {
+ if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
+ ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
+ ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
+ endnetgrent();
+ return (1);
+ }
+ }
+ endnetgrent();
+ return (0);
+}
+#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
+#endif /* HAVE_INNETGR */
+
+
+
+#ifndef HAVE_INITGROUPS
+/****************************************************************************
+ some systems don't have an initgroups call
+****************************************************************************/
+int rep_initgroups(char *name, gid_t id)
+{
+#ifndef HAVE_SETGROUPS
+ /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
+ errno = ENOSYS;
+ return -1;
+#else /* HAVE_SETGROUPS */
+
+#include <grp.h>
+
+ gid_t *grouplst = NULL;
+ int max_gr = 32;
+ int ret;
+ int i,j;
+ struct group *g;
+ char *gr;
+
+ if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ grouplst[0] = id;
+ i = 1;
+ while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
+ if (g->gr_gid == id)
+ continue;
+ j = 0;
+ gr = g->gr_mem[0];
+ while (gr && (*gr != (char)NULL)) {
+ if (strcmp(name,gr) == 0) {
+ grouplst[i] = g->gr_gid;
+ i++;
+ gr = (char *)NULL;
+ break;
+ }
+ gr = g->gr_mem[++j];
+ }
+ }
+ endgrent();
+ ret = setgroups(i, grouplst);
+ free(grouplst);
+ return ret;
+#endif /* HAVE_SETGROUPS */
+}
+#endif /* HAVE_INITGROUPS */
+
+
+#if (defined(SecureWare) && defined(SCO))
+/* This is needed due to needing the nap() function but we don't want
+ to include the Xenix libraries since that will break other things...
+ BTW: system call # 0x0c28 is the same as calling nap() */
+long nap(long milliseconds) {
+ return syscall(0x0c28, milliseconds);
+ }
+#endif
+
+
+#ifndef HAVE_MEMMOVE
+/*******************************************************************
+safely copies memory, ensuring no overlap problems.
+this is only used if the machine does not have it's own memmove().
+this is not the fastest algorithm in town, but it will do for our
+needs.
+********************************************************************/
+void *rep_memmove(void *dest,const void *src,int size)
+{
+ unsigned long d,s;
+ int i;
+ if (dest==src || !size) return(dest);
+
+ d = (unsigned long)dest;
+ s = (unsigned long)src;
+
+ if ((d >= (s+size)) || (s >= (d+size))) {
+ /* no overlap */
+ memcpy(dest,src,size);
+ return(dest);
+ }
+
+ if (d < s) {
+ /* we can forward copy */
+ if (s-d >= sizeof(int) &&
+ !(s%sizeof(int)) &&
+ !(d%sizeof(int)) &&
+ !(size%sizeof(int))) {
+ /* do it all as words */
+ int *idest = (int *)dest;
+ int *isrc = (int *)src;
+ size /= sizeof(int);
+ for (i=0;i<size;i++) idest[i] = isrc[i];
+ } else {
+ /* simplest */
+ char *cdest = (char *)dest;
+ char *csrc = (char *)src;
+ for (i=0;i<size;i++) cdest[i] = csrc[i];
+ }
+ } else {
+ /* must backward copy */
+ if (d-s >= sizeof(int) &&
+ !(s%sizeof(int)) &&
+ !(d%sizeof(int)) &&
+ !(size%sizeof(int))) {
+ /* do it all as words */
+ int *idest = (int *)dest;
+ int *isrc = (int *)src;
+ size /= sizeof(int);
+ for (i=size-1;i>=0;i--) idest[i] = isrc[i];
+ } else {
+ /* simplest */
+ char *cdest = (char *)dest;
+ char *csrc = (char *)src;
+ for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
+ }
+ }
+ return(dest);
+}
+#endif /* HAVE_MEMMOVE */
+
+#ifndef HAVE_STRDUP
+/****************************************************************************
+duplicate a string
+****************************************************************************/
+char *rep_strdup(const char *s)
+{
+ size_t len;
+ char *ret;
+
+ if (!s) return(NULL);
+
+ len = strlen(s)+1;
+ ret = (char *)malloc(len);
+ if (!ret) return(NULL);
+ memcpy(ret,s,len);
+ return(ret);
+}
+#endif /* HAVE_STRDUP */
+
+#ifndef WITH_PTHREADS
+/* REWRITE: not thread safe */
+#ifdef REPLACE_INET_NTOA
+char *rep_inet_ntoa(struct in_addr ip)
+{
+ uint8_t *p = (uint8_t *)&ip.s_addr;
+ static char buf[18];
+ slprintf(buf, 17, "%d.%d.%d.%d",
+ (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
+ return buf;
+}
+#endif /* REPLACE_INET_NTOA */
+#endif
+
+#ifndef HAVE_SETLINEBUF
+void rep_setlinebuf(FILE *stream)
+{
+ setvbuf(stream, (char *)NULL, _IOLBF, 0);
+}
+#endif /* HAVE_SETLINEBUF */
+
+#ifndef HAVE_VSYSLOG
+#ifdef HAVE_SYSLOG
+void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
+{
+ char *msg = NULL;
+ vasprintf(&msg, format, arglist);
+ if (!msg)
+ return;
+ syslog(facility_priority, "%s", msg);
+ free(msg);
+}
+#endif /* HAVE_SYSLOG */
+#endif /* HAVE_VSYSLOG */
+
+#ifndef HAVE_STRNLEN
+/**
+ Some platforms don't have strnlen
+**/
+ size_t rep_strnlen(const char *s, size_t max)
+{
+ size_t len;
+
+ for (len = 0; len < max; len++) {
+ if (s[len] == '\0') {
+ break;
+ }
+ }
+ return len;
+}
+#endif
+
+#ifndef HAVE_STRNDUP
+/**
+ Some platforms don't have strndup.
+**/
+char *rep_strndup(const char *s, size_t n)
+{
+ char *ret;
+
+ n = strnlen(s, n);
+ ret = malloc(n+1);
+ if (!ret)
+ return NULL;
+ memcpy(ret, s, n);
+ ret[n] = 0;
+
+ return ret;
+}
+#endif
+
+#ifndef HAVE_WAITPID
+int rep_waitpid(pid_t pid,int *status,int options)
+{
+ return wait4(pid, status, options, NULL);
+}
+#endif
+
+#ifndef HAVE_SETEUID
+int rep_seteuid(uid_t euid)
+{
+#ifdef HAVE_SETRESUID
+ return setresuid(-1, euid, -1);
+#else
+# error "You need a seteuid function"
+#endif
+}
+#endif
+
+#ifndef HAVE_SETEGID
+int rep_setegid(gid_t egid)
+{
+#ifdef HAVE_SETRESGID
+ return setresgid(-1, egid, -1);
+#else
+# error "You need a setegid function"
+#endif
+}
+#endif
+
+/*******************************************************************
+os/2 also doesn't have chroot
+********************************************************************/
+#ifndef HAVE_CHROOT
+int rep_chroot(const char *dname)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+/*****************************************************************
+ Possibly replace mkstemp if it is broken.
+*****************************************************************/
+
+#ifndef HAVE_SECURE_MKSTEMP
+int rep_mkstemp(char *template)
+{
+ /* have a reasonable go at emulating it. Hope that
+ the system mktemp() isn't completly hopeless */
+ char *p = mktemp(template);
+ if (!p)
+ return -1;
+ return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
+}
+#endif
+
+#ifndef HAVE_MKDTEMP
+char *rep_mkdtemp(char *template)
+{
+ char *dname;
+
+ if ((dname = mktemp(template))) {
+ if (mkdir(dname, 0700) >= 0) {
+ return dname;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_PREAD
+ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
+{
+ if (lseek(__fd, __offset, SEEK_SET) != __offset) {
+ return -1;
+ }
+ return read(__fd, __buf, __nbytes);
+}
+#endif
+
+#ifndef HAVE_PWRITE
+ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
+{
+ if (lseek(__fd, __offset, SEEK_SET) != __offset) {
+ return -1;
+ }
+ return write(__fd, __buf, __nbytes);
+}
+#endif
+
+#ifndef HAVE_STRCASESTR
+char *rep_strcasestr(const char *haystack, const char *needle)
+{
+ const char *s;
+ size_t nlen = strlen(needle);
+ for (s=haystack;*s;s++) {
+ if (toupper(*needle) == toupper(*s) &&
+ strncasecmp(s, needle, nlen) == 0) {
+ return (char *)((intptr_t)s);
+ }
+ }
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_STRTOK_R
+/* based on GLIBC version, copyright Free Software Foundation */
+char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
+{
+ char *token;
+
+ if (s == NULL) s = *save_ptr;
+
+ s += strspn(s, delim);
+ if (*s == '\0') {
+ *save_ptr = s;
+ return NULL;
+ }
+
+ token = s;
+ s = strpbrk(token, delim);
+ if (s == NULL) {
+ *save_ptr = token + strlen(token);
+ } else {
+ *s = '\0';
+ *save_ptr = s + 1;
+ }
+
+ return token;
+}
+#endif
+
+#ifndef HAVE_STRTOLL
+long long int rep_strtoll(const char *str, char **endptr, int base)
+{
+#ifdef HAVE_STRTOQ
+ return strtoq(str, endptr, base);
+#elif defined(HAVE___STRTOLL)
+ return __strtoll(str, endptr, base);
+#elif SIZEOF_LONG == SIZEOF_LONG_LONG
+ return (long long int) strtol(str, endptr, base);
+#else
+# error "You need a strtoll function"
+#endif
+}
+#endif
+
+
+#ifndef HAVE_STRTOULL
+unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
+{
+#ifdef HAVE_STRTOUQ
+ return strtouq(str, endptr, base);
+#elif defined(HAVE___STRTOULL)
+ return __strtoull(str, endptr, base);
+#elif SIZEOF_LONG == SIZEOF_LONG_LONG
+ return (unsigned long long int) strtoul(str, endptr, base);
+#else
+# error "You need a strtoull function"
+#endif
+}
+#endif
+
+#ifndef HAVE_SETENV
+int rep_setenv(const char *name, const char *value, int overwrite)
+{
+ char *p;
+ size_t l1, l2;
+ int ret;
+
+ if (!overwrite && getenv(name)) {
+ return 0;
+ }
+
+ l1 = strlen(name);
+ l2 = strlen(value);
+
+ p = malloc(l1+l2+2);
+ if (p == NULL) {
+ return -1;
+ }
+ memcpy(p, name, l1);
+ p[l1] = '=';
+ memcpy(p+l1+1, value, l2);
+ p[l1+l2+1] = 0;
+
+ ret = putenv(p);
+ if (ret != 0) {
+ free(p);
+ }
+
+ return ret;
+}
+#endif
+
+#ifndef HAVE_SOCKETPAIR
+int rep_socketpair(int d, int type, int protocol, int sv[2])
+{
+ if (d != AF_UNIX) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (protocol != 0) {
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ if (type != SOCK_STREAM) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ return pipe(sv);
+}
+#endif
diff --git a/source/lib/replace/replace.h b/source/lib/replace/replace.h
new file mode 100644
index 00000000000..d75394aa1fc
--- /dev/null
+++ b/source/lib/replace/replace.h
@@ -0,0 +1,408 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ macros to go along with the lib/replace/ portability layer code
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Jelmer Vernooij 2006
+
+ ** NOTE! The following LGPL license applies to the replace
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _LIBREPLACE_REPLACE_H
+#define _LIBREPLACE_REPLACE_H
+
+#ifndef NO_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STANDARDS_H
+#include <standards.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#include "win32_replace.h"
+#endif
+
+#ifdef __COMPAR_FN_T
+#define QSORT_CAST (__compar_fn_t)
+#endif
+
+#ifndef QSORT_CAST
+#define QSORT_CAST (int (*)(const void *, const void *))
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+/* force off HAVE_INTTYPES_H so that roken doesn't try to include both,
+ which causes a warning storm on irix */
+#undef HAVE_INTTYPES_H
+#elif HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+
+#ifndef HAVE_STRERROR
+extern char *sys_errlist[];
+#define strerror(i) sys_errlist[i]
+#endif
+
+#ifndef HAVE_ERRNO_DECL
+extern int errno;
+#endif
+
+#ifndef HAVE_STRDUP
+#define strdup rep_strdup
+char *rep_strdup(const char *s);
+#endif
+
+#ifndef HAVE_MEMMOVE
+#define memmove rep_memmove
+void *rep_memmove(void *dest,const void *src,int size);
+#endif
+
+#if !defined(HAVE_MKTIME) || !defined(HAVE_TIMEGM)
+#include "system/time.h"
+#endif
+
+#ifndef HAVE_MKTIME
+#define mktime rep_mktime
+time_t rep_mktime(struct tm *t);
+#endif
+
+#ifndef HAVE_TIMEGM
+struct tm;
+#define timegm rep_timegm
+time_t rep_timegm(struct tm *tm);
+#endif
+
+#ifndef HAVE_STRLCPY
+#define strlcpy rep_strlcpy
+size_t rep_strlcpy(char *d, const char *s, size_t bufsize);
+#endif
+
+#ifndef HAVE_STRLCAT
+#define strlcat rep_strlcat
+size_t rep_strlcat(char *d, const char *s, size_t bufsize);
+#endif
+
+#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
+#undef HAVE_STRNDUP
+#define strndup rep_strndup
+char *rep_strndup(const char *s, size_t n);
+#endif
+
+#if (defined(BROKEN_STRNLEN) || !defined(HAVE_STRNLEN))
+#undef HAVE_STRNLEN
+#define strnlen rep_strnlen
+size_t rep_strnlen(const char *s, size_t n);
+#endif
+
+#ifndef HAVE_SETENV
+#define setenv rep_setenv
+int rep_setenv(const char *name, const char *value, int overwrite);
+#endif
+
+#ifndef HAVE_SETEUID
+#define seteuid rep_seteuid
+int rep_seteuid(uid_t);
+#endif
+
+#ifndef HAVE_SETEGID
+#define setegid rep_setegid
+int rep_setegid(gid_t);
+#endif
+
+#ifndef HAVE_SETLINEBUF
+#define setlinebuf rep_setlinebuf
+void rep_setlinebuf(FILE *);
+#endif
+
+#ifndef HAVE_STRCASESTR
+#define strcasestr rep_strcasestr
+char *rep_strcasestr(const char *haystack, const char *needle);
+#endif
+
+#ifndef HAVE_STRTOK_R
+#define strtok_r rep_strtok_r
+char *rep_strtok_r(char *s, const char *delim, char **save_ptr);
+#endif
+
+#ifndef HAVE_STRTOLL
+#define strtoll rep_strtoll
+long long int rep_strtoll(const char *str, char **endptr, int base);
+#endif
+
+#ifndef HAVE_STRTOULL
+#define strtoull rep_strtoull
+unsigned long long int rep_strtoull(const char *str, char **endptr, int base);
+#endif
+
+#ifndef HAVE_FTRUNCATE
+#define ftruncate rep_ftruncate
+int rep_ftruncate(int,off_t);
+#endif
+
+#ifndef HAVE_INITGROUPS
+#define ftruncate rep_ftruncate
+int rep_initgroups(char *name, gid_t id);
+#endif
+
+#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET)
+#define bzero(a,b) memset((a),'\0',(b))
+#endif
+
+#ifndef HAVE_DLERROR
+#define dlerror rep_dlerror
+char *rep_dlerror(void);
+#endif
+
+#ifndef HAVE_DLOPEN
+#define dlopen rep_dlopen
+void *rep_dlopen(const char *name, int flags);
+#endif
+
+#ifndef HAVE_DLSYM
+#define dlsym rep_dlsym
+void *rep_dlsym(void *handle, const char *symbol);
+#endif
+
+#ifndef HAVE_DLCLOSE
+#define dlclose rep_dlclose
+int rep_dlclose(void *handle);
+#endif
+
+#ifndef HAVE_SOCKETPAIR
+#define socketpair rep_socketpair
+int rep_socketpair(int d, int type, int protocol, int sv[2]);
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+#ifndef HAVE_VASPRINTF
+#define vasprintf rep_vasprintf
+int rep_vasprintf(char **ptr, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0);
+#endif
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+#define snprintf rep_snprintf
+int rep_snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4);
+#endif
+
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+#define vsnprintf rep_vsnprintf
+int rep_vsnprintf(char *,size_t ,const char *, va_list ap) PRINTF_ATTRIBUTE(3,0);
+#endif
+
+#ifndef HAVE_ASPRINTF
+#define asprintf rep_asprintf
+int rep_asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
+#endif
+
+#ifndef HAVE_VSYSLOG
+#ifdef HAVE_SYSLOG
+#define vsyslog rep_vsyslog
+void rep_vsyslog (int facility_priority, const char *format, va_list arglist) PRINTF_ATTRIBUTE(2,0);
+#endif
+#endif
+
+/* we used to use these fns, but now we have good replacements
+ for snprintf and vsnprintf */
+#define slprintf snprintf
+
+
+#ifndef HAVE_VA_COPY
+#undef va_copy
+#ifdef HAVE___VA_COPY
+#define va_copy(dest, src) __va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
+#ifndef HAVE_VOLATILE
+#define volatile
+#endif
+
+#ifndef HAVE_COMPARISON_FN_T
+typedef int (*comparison_fn_t)(const void *, const void *);
+#endif
+
+/* Load header file for dynamic linking stuff */
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 0
+#endif
+
+#ifndef HAVE_SECURE_MKSTEMP
+#define mkstemp(path) rep_mkstemp(path)
+int rep_mkstemp(char *temp);
+#endif
+
+#ifndef HAVE_MKDTEMP
+#define mkdtemp rep_mkdtemp
+char *rep_mkdtemp(char *template);
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* The extra casts work around common compiler bugs. */
+#define _TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+ It is necessary at least when t == time_t. */
+#define _TYPE_MINIMUM(t) ((t) (_TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
+#define _TYPE_MAXIMUM(t) ((t) (~ (t) 0 - _TYPE_MINIMUM (t)))
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 64
+#endif
+
+#ifndef UINT16_MAX
+#define UINT16_MAX 65535
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#ifndef UINT64_MAX
+#define UINT64_MAX ((uint64_t)-1)
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef INT32_MAX
+#define INT32_MAX _TYPE_MAXIMUM(int32_t)
+#endif
+
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
+#if !defined(HAVE_BOOL)
+#ifdef HAVE__Bool
+#define bool _Bool
+#else
+typedef int bool;
+#endif
+#endif
+
+/*
+ * to prevent <rpcsvc/yp_prot.h> from doing a redefine of 'bool'
+ *
+ * IRIX, HPUX, MacOS 10 and Solaris need BOOL_DEFINED
+ * Tru64 needs _BOOL_EXISTS
+ * AIX needs _BOOL,_TRUE,_FALSE
+ */
+#ifndef BOOL_DEFINED
+#define BOOL_DEFINED
+#endif
+#ifndef _BOOL_EXISTS
+#define _BOOL_EXISTS
+#endif
+#ifndef _BOOL
+#define _BOOL
+#endif
+
+#ifndef __bool_true_false_are_defined
+#define __bool_true_false_are_defined
+#endif
+
+#ifndef true
+#define true (1)
+#endif
+#ifndef false
+#define false (0)
+#endif
+
+#ifndef _TRUE
+#define _TRUE true
+#endif
+#ifndef _FALSE
+#define _FALSE false
+#endif
+
+#ifndef HAVE_FUNCTION_MACRO
+#ifdef HAVE_func_MACRO
+#define __FUNCTION__ __func__
+#else
+#define __FUNCTION__ ("")
+#endif
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#if MMAP_BLACKLIST
+#undef HAVE_MMAP
+#endif
+
+#endif /* _LIBREPLACE_REPLACE_H */
diff --git a/source/lib/replace/samba.m4 b/source/lib/replace/samba.m4
new file mode 100644
index 00000000000..3769c7f50e9
--- /dev/null
+++ b/source/lib/replace/samba.m4
@@ -0,0 +1,23 @@
+AC_LIBREPLACE_BROKEN_CHECKS
+
+SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL}])
+SMB_ENABLE(LIBREPLACE_EXT)
+
+LIBREPLACE_DIR=`echo ${libreplacedir} |sed -e 's/^\.\///g'`
+
+LIBREPLACE_OBJS=""
+for obj in ${LIBREPLACEOBJ}; do
+ LIBREPLACE_OBJS="${LIBREPLACE_OBJS} ${LIBREPLACE_DIR}/${obj}"
+done
+
+SMB_SUBSYSTEM(LIBREPLACE,
+ [${LIBREPLACE_OBJS}],
+ [LIBREPLACE_EXT],
+ [-Ilib/replace])
+
+LIBREPLACE_HOSTCC_OBJS=`echo ${LIBREPLACE_OBJS} |sed -e 's/\.o/\.ho/g'`
+
+SMB_SUBSYSTEM(LIBREPLACE_HOSTCC,
+ [${LIBREPLACE_HOSTCC_OBJS}],
+ [],
+ [-Ilib/replace])
diff --git a/source/lib/snprintf.c b/source/lib/replace/snprintf.c
index 8ff76ab1165..9f8a7657e52 100644
--- a/source/lib/snprintf.c
+++ b/source/lib/replace/snprintf.c
@@ -103,11 +103,8 @@
*
**************************************************************/
-#ifndef NO_CONFIG_H
-#include "config.h"
-#else
-#define NULL 0
-#endif
+#include "replace.h"
+#include "system/locale.h"
#ifdef TEST_SNPRINTF /* need math library headers for testing */
@@ -121,22 +118,6 @@
# include <math.h>
#endif /* TEST_SNPRINTF */
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#include <sys/types.h>
-#include <stdarg.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
#include <stdio.h>
@@ -145,6 +126,9 @@
void dummy_snprintf(void) {}
#endif /* HAVE_SNPRINTF, etc */
+/* yes this really must be a ||. Don't muck with this (tridge) */
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
@@ -197,6 +181,7 @@
#define DP_C_LONG 3
#define DP_C_LDOUBLE 4
#define DP_C_LLONG 5
+#define DP_C_SIZET 6
/* Chunk types */
#define CNK_FMT_STR 0
@@ -216,9 +201,6 @@
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
-/* yes this really must be a ||. Don't muck with this (tridge) */
-#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
-
struct pr_chunk {
int type; /* chunk type */
int num; /* parameter number */
@@ -242,7 +224,7 @@ struct pr_chunk_x {
int num;
};
-static size_t dopr(char *buffer, size_t maxlen, const char *format,
+static int dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
@@ -255,7 +237,7 @@ static struct pr_chunk *new_chunk(void);
static int add_cnk_list_entry(struct pr_chunk_x **list,
int max_num, struct pr_chunk *chunk);
-static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
+static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
{
char ch;
int state;
@@ -269,7 +251,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
struct pr_chunk *cnk = NULL;
struct pr_chunk_x *clist = NULL;
int max_pos;
- size_t ret = -1;
+ int ret = -1;
VA_COPY(args, args_in);
@@ -467,6 +449,10 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
cnk->cflags = DP_C_LDOUBLE;
ch = *format++;
break;
+ case 'z':
+ cnk->cflags = DP_C_SIZET;
+ ch = *format++;
+ break;
default:
break;
}
@@ -575,6 +561,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
cnk->value = va_arg (args, long int);
else if (cnk->cflags == DP_C_LLONG)
cnk->value = va_arg (args, LLONG);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->value = va_arg (args, ssize_t);
else
cnk->value = va_arg (args, int);
@@ -592,6 +580,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
cnk->value = (unsigned long int)va_arg (args, unsigned long int);
else if (cnk->cflags == DP_C_LLONG)
cnk->value = (LLONG)va_arg (args, unsigned LLONG);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->value = (size_t)va_arg (args, size_t);
else
cnk->value = (unsigned int)va_arg (args, unsigned int);
@@ -644,6 +634,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
cnk->pnum = va_arg (args, long int *);
else if (cnk->cflags == DP_C_LLONG)
cnk->pnum = va_arg (args, LLONG *);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->pnum = va_arg (args, ssize_t *);
else
cnk->pnum = va_arg (args, int *);
@@ -725,6 +717,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
*((long int *)(cnk->pnum)) = (long int)currlen;
else if (cnk->cflags == DP_C_LLONG)
*((LLONG *)(cnk->pnum)) = (LLONG)currlen;
+ else if (cnk->cflags == DP_C_SIZET)
+ *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen;
else
*((int *)(cnk->pnum)) = (int)currlen;
break;
@@ -748,6 +742,8 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
ret = currlen;
done:
+ va_end(args);
+
while (chunks) {
cnk = chunks->next;
free(chunks);
@@ -920,7 +916,7 @@ static LLONG ROUND(LDOUBLE value)
static double my_modf(double x0, double *iptr)
{
int i;
- LLONG l;
+ LLONG l=0;
double x = x0;
double f = 1.0;
@@ -1190,11 +1186,10 @@ static int add_cnk_list_entry(struct pr_chunk_x **list,
return max;
}
- int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+ int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
-#define vsnprintf smb_vsnprintf
#endif
/* yes this really must be a ||. Don't muck with this (tridge)
@@ -1204,7 +1199,7 @@ static int add_cnk_list_entry(struct pr_chunk_x **list,
* that doesn't work properly according to the autoconf test.
*/
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
-int smb_snprintf(char *str,size_t count,const char *fmt,...)
+ int snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
@@ -1214,7 +1209,48 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
va_end(ap);
return ret;
}
-#define snprintf smb_snprintf
+#endif
+
+#ifndef HAVE_C99_VSNPRINTF
+ int printf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ char *s;
+
+ s = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(&s, fmt, ap);
+ va_end(ap);
+
+ if (s) {
+ fwrite(s, 1, strlen(s), stdout);
+ }
+ free(s);
+
+ return ret;
+}
+#endif
+
+#ifndef HAVE_C99_VSNPRINTF
+ int fprintf(FILE *stream, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ char *s;
+
+ s = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(&s, fmt, ap);
+ va_end(ap);
+
+ if (s) {
+ fwrite(s, 1, strlen(s), stream);
+ }
+ free(s);
+
+ return ret;
+}
#endif
#endif
@@ -1226,16 +1262,16 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
va_list ap2;
VA_COPY(ap2, ap);
-
ret = vsnprintf(NULL, 0, format, ap2);
+ va_end(ap2);
if (ret <= 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
VA_COPY(ap2, ap);
-
ret = vsnprintf(*ptr, ret+1, format, ap2);
+ va_end(ap2);
return ret;
}
@@ -1260,6 +1296,7 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
#ifdef TEST_SNPRINTF
int sprintf(char *str,const char *fmt,...);
+ int printf(const char *fmt,...);
int main (void)
{
@@ -1329,15 +1366,20 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
int fail = 0;
int num = 0;
int l1, l2;
+ char *ss_fmt[] = {
+ "%zd",
+ "%zu",
+ NULL
+ };
+ size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0};
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
- l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
- l2 = sprintf(buf1, fp_fmt[x], fp_nums[y]);
- sprintf (buf2, fp_fmt[x], fp_nums[y]);
+ l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
+ l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]);
buf1[1023] = buf2[1023] = '\0';
if (strcmp (buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
@@ -1351,9 +1393,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
for (x = 0; int_fmt[x] ; x++) {
for (y = 0; int_nums[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
- l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
- l2 = sprintf(buf1, int_fmt[x], int_nums[y]);
- sprintf (buf2, int_fmt[x], int_nums[y]);
+ l1 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
+ l2 = sprintf (buf2, int_fmt[x], int_nums[y]);
buf1[1023] = buf2[1023] = '\0';
if (strcmp (buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
@@ -1367,9 +1408,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
for (x = 0; str_fmt[x] ; x++) {
for (y = 0; str_vals[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
- l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
- l2 = sprintf(buf1, str_fmt[x], str_vals[y]);
- sprintf (buf2, str_fmt[x], str_vals[y]);
+ l1 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
+ l2 = sprintf (buf2, str_fmt[x], str_vals[y]);
buf1[1023] = buf2[1023] = '\0';
if (strcmp (buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
@@ -1384,9 +1424,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
for (x = 0; ll_fmt[x] ; x++) {
for (y = 0; ll_nums[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
- l1 = snprintf(NULL, 0, ll_fmt[x], ll_nums[y]);
- l2 = sprintf(buf1, ll_fmt[x], ll_nums[y]);
- sprintf (buf2, ll_fmt[x], ll_nums[y]);
+ l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]);
+ l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]);
buf1[1023] = buf2[1023] = '\0';
if (strcmp (buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
@@ -1433,6 +1472,21 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
"%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
fail++;
}
+
+ for (x = 0; ss_fmt[x] ; x++) {
+ for (y = 0; ss_nums[y] != 0 ; y++) {
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x], ss_nums[y]);
+ l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ ss_fmt[x], l1, buf1, l2, buf2);
+ fail++;
+ }
+ num++;
+ }
+ }
#if 0
buf1[0] = buf2[0] = '\0';
l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890);
diff --git a/source/lib/replace/system/README b/source/lib/replace/system/README
new file mode 100644
index 00000000000..69a2b80b56c
--- /dev/null
+++ b/source/lib/replace/system/README
@@ -0,0 +1,4 @@
+This directory contains wrappers around logical groups of system
+include files. The idea is to avoid #ifdef blocks in the main code,
+and instead put all the necessary conditional includes in subsystem
+specific header files in this directory.
diff --git a/source/smbwrapper/realcalls.c b/source/lib/replace/system/aio.h
index b64f4a43dbf..45154ccb27a 100644
--- a/source/smbwrapper/realcalls.c
+++ b/source/lib/replace/system/aio.h
@@ -1,7 +1,11 @@
+#ifndef _system_aio_h
+#define _system_aio_h
/*
Unix SMB/CIFS implementation.
- SMB wrapper functions for calls that syscall() can't do
- Copyright (C) Andrew Tridgell 1998
+
+ AIO system include wrappers
+
+ Copyright (C) Andrew Tridgell 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,31 +22,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "includes.h"
-#include "realcalls.h"
-
-#ifdef REPLACE_UTIME
-int real_utime(const char *name, struct utimbuf *buf)
-{
- struct timeval tv[2];
-
- tv[0].tv_sec = buf->actime;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = buf->modtime;
- tv[1].tv_usec = 0;
-
- return real_utimes(name, &tv[0]);
-}
+#ifdef HAVE_LIBAIO_H
+#include <libaio.h>
#endif
-#ifdef REPLACE_UTIMES
-int real_utimes(const char *name, struct timeval tv[2])
-{
- struct utimbuf buf;
-
- buf.actime = tv[0].tv_sec;
- buf.modtime = tv[1].tv_sec;
-
- return real_utime(name, &buf);
-}
#endif
diff --git a/source/lib/replace/system/capability.h b/source/lib/replace/system/capability.h
new file mode 100644
index 00000000000..6ed8ae8de02
--- /dev/null
+++ b/source/lib/replace/system/capability.h
@@ -0,0 +1,41 @@
+#ifndef _system_capability_h
+#define _system_capability_h
+/*
+ Unix SMB/CIFS implementation.
+
+ capability system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_SYS_CAPABILITY_H
+
+#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H)
+#define _I386_STATFS_H
+#define BROKEN_REDHAT_7_STATFS_WORKAROUND
+#endif
+
+#include <sys/capability.h>
+
+#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
+#undef _I386_STATFS_H
+#undef BROKEN_REDHAT_7_STATFS_WORKAROUND
+#endif
+
+#endif
+
+#endif
diff --git a/source/lib/replace/system/config.m4 b/source/lib/replace/system/config.m4
new file mode 100644
index 00000000000..4d66317a5ee
--- /dev/null
+++ b/source/lib/replace/system/config.m4
@@ -0,0 +1,31 @@
+# filesys
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(fcntl.h sys/fcntl.h sys/acl.h sys/resource.h sys/ioctl.h sys/mode.h sys/filio.h sys/fs/s5param.h sys/filsys.h )
+
+# select
+AC_CHECK_HEADERS(sys/select.h)
+
+# time
+AC_CHECK_HEADERS(sys/time.h utime.h)
+AC_HEADER_TIME
+
+# wait
+AC_HEADER_SYS_WAIT
+
+# capability
+AC_CHECK_HEADERS(sys/capability.h)
+
+# passwd
+AC_CHECK_HEADERS(grp.h sys/id.h compat.h shadow.h sys/priv.h pwd.h sys/security.h)
+
+# locale
+AC_CHECK_HEADERS(ctype.h locale.h)
+
+# glob
+AC_CHECK_HEADERS(fnmatch.h)
+
+# shmem
+AC_CHECK_HEADERS(sys/ipc.h sys/mman.h sys/shm.h )
+
+# terminal
+AC_CHECK_HEADERS(termios.h termio.h sys/termio.h )
diff --git a/source/lib/replace/system/dir.h b/source/lib/replace/system/dir.h
new file mode 100644
index 00000000000..64e413c9079
--- /dev/null
+++ b/source/lib/replace/system/dir.h
@@ -0,0 +1,64 @@
+#ifndef _system_dir_h
+#define _system_dir_h
+/*
+ Unix SMB/CIFS implementation.
+
+ directory system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifndef HAVE_MKDIR_MODE
+#define mkdir(dir, mode) mkdir(dir)
+#endif
+
+/* Test whether a file name is the "." or ".." directory entries.
+ * These really should be inline functions.
+ */
+#ifndef ISDOT
+#define ISDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '\0' \
+ )
+#endif
+
+#ifndef ISDOTDOT
+#define ISDOTDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '.' && \
+ *(((const char *)(path)) + 2) == '\0' \
+ )
+#endif
+
+#endif
diff --git a/source/lib/replace/system/filesys.h b/source/lib/replace/system/filesys.h
new file mode 100644
index 00000000000..1e48f7ab404
--- /dev/null
+++ b/source/lib/replace/system/filesys.h
@@ -0,0 +1,170 @@
+#ifndef _system_filesys_h
+#define _system_filesys_h
+/*
+ Unix SMB/CIFS implementation.
+
+ filesystem system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+
+#ifdef HAVE_SYS_FS_S5PARAM_H
+#include <sys/fs/s5param.h>
+#endif
+
+#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY)
+#include <sys/filsys.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_DUSTAT_H
+#include <sys/dustat.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#include <sys/file.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_MODE_H
+/* apparently AIX needs this for S_ISLNK */
+#ifndef S_ISLNK
+#include <sys/mode.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * Veritas File System. Often in addition to native.
+ * Quotas different.
+ */
+#if defined(HAVE_SYS_FS_VX_QUOTA_H)
+#define VXFS_QUOTA
+#endif
+
+#if HAVE_SYS_ATTRIBUTES_H
+#include <sys/attributes.h>
+#endif
+
+/* mutually exclusive (SuSE 8.2) */
+#if HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#elif HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+/* Some POSIX definitions for those without */
+
+#ifndef S_IFDIR
+#define S_IFDIR 0x4000
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR)
+#endif
+#ifndef S_IRWXU
+#define S_IRWXU 00700 /* read, write, execute: owner */
+#endif
+#ifndef S_IRUSR
+#define S_IRUSR 00400 /* read permission: owner */
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 00200 /* write permission: owner */
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 00100 /* execute permission: owner */
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG 00070 /* read, write, execute: group */
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 00040 /* read permission: group */
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 00020 /* write permission: group */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 00010 /* execute permission: group */
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO 00007 /* read, write, execute: other */
+#endif
+#ifndef S_IROTH
+#define S_IROTH 00004 /* read permission: other */
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 00002 /* write permission: other */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 00001 /* execute permission: other */
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 256
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#endif
diff --git a/source/lib/replace/system/glob.h b/source/lib/replace/system/glob.h
new file mode 100644
index 00000000000..0e51f397c69
--- /dev/null
+++ b/source/lib/replace/system/glob.h
@@ -0,0 +1,33 @@
+#ifndef _system_glob_h
+#define _system_glob_h
+/*
+ Unix SMB/CIFS implementation.
+
+ glob system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif
+
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
+#endif
diff --git a/source/lib/replace/system/iconv.h b/source/lib/replace/system/iconv.h
new file mode 100644
index 00000000000..abc2d6f4e1b
--- /dev/null
+++ b/source/lib/replace/system/iconv.h
@@ -0,0 +1,53 @@
+#ifndef _system_iconv_h
+#define _system_iconv_h
+/*
+ Unix SMB/CIFS implementation.
+
+ iconv memory system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#if !defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
+#define HAVE_ICONV
+#endif
+
+#if !defined(HAVE_GICONV) && defined(HAVE_GICONV_H)
+#define HAVE_GICONV
+#endif
+
+#if !defined(HAVE_BICONV) && defined(HAVE_BICONV_H)
+#define HAVE_BICONV
+#endif
+
+#ifdef HAVE_NATIVE_ICONV
+#if defined(HAVE_ICONV)
+#include <iconv.h>
+#elif defined(HAVE_GICONV)
+#include <giconv.h>
+#elif defined(HAVE_BICONV)
+#include <biconv.h>
+#endif
+#endif /* HAVE_NATIVE_ICONV */
+
+/* needed for some systems without iconv. Doesn't really matter
+ what error code we use */
+#ifndef EILSEQ
+#define EILSEQ EIO
+#endif
+
+#endif
diff --git a/source/lib/replace/system/kerberos.h b/source/lib/replace/system/kerberos.h
new file mode 100644
index 00000000000..1617b96aad1
--- /dev/null
+++ b/source/lib/replace/system/kerberos.h
@@ -0,0 +1,132 @@
+#ifndef _system_kerberos_h
+#define _system_kerberos_h
+
+/*
+ Unix SMB/CIFS implementation.
+
+ kerberos system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_KRB5
+/* Whether the krb5_address struct has a addrtype property */
+/* #undef HAVE_ADDRTYPE_IN_KRB5_ADDRESS */
+/* Whether the krb5_address struct has a addr_type property */
+#define HAVE_ADDR_TYPE_IN_KRB5_ADDRESS 1
+/* Define to 1 if you have the `gsskrb5_extract_authz_data_from_sec_context' */
+#define HAVE_GSSKRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT 1
+/* Define to 1 if you have the `gsskrb5_get_initiator_subkey' function. */
+#define HAVE_GSSKRB5_GET_INITIATOR_SUBKEY 1
+/* Define to 1 if you have the `gsskrb5_register_acceptor_identity' function. */
+#define HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY 1
+/* Define to 1 if you have the `gss_krb5_ccache_name' function. */
+#define HAVE_GSS_KRB5_CCACHE_NAME 1
+/* Define to 1 if you have the `krb5_addlog_func' function. */
+#define HAVE_KRB5_ADDLOG_FUNC 1
+/* Define to 1 if you have the `krb5_auth_con_setkey' function. */
+#define HAVE_KRB5_AUTH_CON_SETKEY 1
+/* Define to 1 if you have the `krb5_auth_con_setuseruserkey' function. */
+/* #undef HAVE_KRB5_AUTH_CON_SETUSERUSERKEY */
+/* Define to 1 if you have the `krb5_c_enctype_compare' function. */
+#define HAVE_KRB5_C_ENCTYPE_COMPARE 1
+/* Define to 1 if you have the `krb5_c_verify_checksum' function. */
+#define HAVE_KRB5_C_VERIFY_CHECKSUM 1
+/* Whether the type krb5_encrypt_block exists */
+/* #undef HAVE_KRB5_ENCRYPT_BLOCK */
+/* Define to 1 if you have the `krb5_encrypt_data' function. */
+/* #undef HAVE_KRB5_ENCRYPT_DATA */
+/* Define to 1 if you have the `krb5_enctypes_compatible_keys' function. */
+#define HAVE_KRB5_ENCTYPES_COMPATIBLE_KEYS 1
+/* Define to 1 if you have the `krb5_free_data_contents' function. */
+#define HAVE_KRB5_FREE_DATA_CONTENTS 1
+/* Define to 1 if you have the `krb5_free_error_string' function. */
+#define HAVE_KRB5_FREE_ERROR_STRING 1
+/* Define to 1 if you have the `krb5_free_keytab_entry_contents' function. */
+/* #undef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS */
+/* Define to 1 if you have the `krb5_free_ktypes' function. */
+/* #undef HAVE_KRB5_FREE_KTYPES */
+/* Define to 1 if you have the `krb5_free_unparsed_name' function. */
+/* #undef HAVE_KRB5_FREE_UNPARSED_NAME */
+/* Define to 1 if you have the `krb5_get_default_in_tkt_etypes' function. */
+#define HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES 1
+/* Define to 1 if you have the `krb5_get_error_string' function. */
+#define HAVE_KRB5_GET_ERROR_STRING 1
+/* Define to 1 if you have the `krb5_get_permitted_enctypes' function. */
+/* #undef HAVE_KRB5_GET_PERMITTED_ENCTYPES */
+/* Define to 1 if you have the `krb5_get_pw_salt' function. */
+#define HAVE_KRB5_GET_PW_SALT 1
+/* Define to 1 if you have the <krb5.h> header file. */
+#define HAVE_KRB5_H 1
+/* Define to 1 if you have the `krb5_initlog' function. */
+#define HAVE_KRB5_INITLOG 1
+/* Define to 1 if you have the `krb5_kdc_default_config' function. */
+#define HAVE_KRB5_KDC_DEFAULT_CONFIG 1
+/* Whether the krb5_creds struct has a keyblock property */
+/* #undef HAVE_KRB5_KEYBLOCK_IN_CREDS */
+/* Whether the krb5_keyblock struct has a keyvalue property */
+#define HAVE_KRB5_KEYBLOCK_KEYVALUE 1
+/* Whether krb5_keytab_entry has key member */
+/* #undef HAVE_KRB5_KEYTAB_ENTRY_KEY */
+/* Whether krb5_keytab_entry has keyblock member */
+#define HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK 1
+/* Define to 1 if you have the `krb5_krbhst_get_addrinfo' function. */
+#define HAVE_KRB5_KRBHST_GET_ADDRINFO 1
+/* Define to 1 if you have the `krb5_kt_compare' function. */
+#define HAVE_KRB5_KT_COMPARE 1
+/* Define to 1 if you have the `krb5_kt_free_entry' function. */
+#define HAVE_KRB5_KT_FREE_ENTRY 1
+/* Whether the type krb5_log_facility exists */
+#define HAVE_KRB5_LOG_FACILITY 1
+/* Define to 1 if you have the `krb5_mk_req_extended' function. */
+#define HAVE_KRB5_MK_REQ_EXTENDED 1
+/* Define to 1 if you have the `krb5_principal2salt' function. */
+/* #undef HAVE_KRB5_PRINCIPAL2SALT */
+/* Define to 1 if you have the `krb5_principal_get_comp_string' function. */
+#define HAVE_KRB5_PRINCIPAL_GET_COMP_STRING 1
+/* Whether krb5_princ_component is available */
+/* #undef HAVE_KRB5_PRINC_COMPONENT */
+/* Whether the krb5_creds struct has a session property */
+#define HAVE_KRB5_SESSION_IN_CREDS 1
+/* Define to 1 if you have the `krb5_set_default_in_tkt_etypes' function. */
+#define HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES 1
+/* Define to 1 if you have the `krb5_set_default_tgs_ktypes' function. */
+/* #undef HAVE_KRB5_SET_DEFAULT_TGS_KTYPES */
+/* Define to 1 if you have the `krb5_set_real_time' function. */
+#define HAVE_KRB5_SET_REAL_TIME 1
+/* Define to 1 if you have the `krb5_set_warn_dest' function. */
+#define HAVE_KRB5_SET_WARN_DEST 1
+/* Define to 1 if you have the `krb5_string_to_key' function. */
+#define HAVE_KRB5_STRING_TO_KEY 1
+/* Define to 1 if you have the `krb5_string_to_key_salt' function. */
+#define HAVE_KRB5_STRING_TO_KEY_SALT 1
+/* Define to 1 if you have the `krb5_ticket_get_authorization_data_type' */
+#define HAVE_KRB5_TICKET_GET_AUTHORIZATION_DATA_TYPE 1
+/* Whether the krb5_ticket struct has a enc_part2 property */
+/* #undef HAVE_KRB5_TKT_ENC_PART2 */
+/* Define to 1 if you have the `krb5_use_enctype' function. */
+/* #undef HAVE_KRB5_USE_ENCTYPE */
+/* Define to 1 if you have the `krb5_verify_checksum' function. */
+#define HAVE_KRB5_VERIFY_CHECKSUM 1
+/* Whether krb5_princ_realm returns krb5_realm or krb5_data */
+#define KRB5_PRINC_REALM_RETURNS_REALM 1
+
+#include "heimdal/lib/krb5/krb5.h"
+#include "heimdal/lib/com_err/com_err.h"
+#endif
+
+#endif
diff --git a/source/tdb/tdbutil.h b/source/lib/replace/system/locale.h
index 1a181a962f2..82b179dc5b8 100644
--- a/source/tdb/tdbutil.h
+++ b/source/lib/replace/system/locale.h
@@ -1,8 +1,12 @@
+#ifndef _system_locale_h
+#define _system_locale_h
+
/*
Unix SMB/CIFS implementation.
- tdb utility functions
- Copyright (C) Andrew Tridgell 1999
- Copyright (C) Rafal Szczesniak 2002
+
+ locale include wrappers
+
+ Copyright (C) Andrew Tridgell 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
@@ -19,20 +23,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef __TDBUTIL_H__
-#define __TDBUTIL_H__
-
-
-/* single node of a list returned by tdb_search_keys */
-typedef struct keys_node
-{
- struct keys_node *prev, *next;
- TDB_DATA node_key;
-} TDB_LIST_NODE;
-
-
-TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*);
-void tdb_search_list_free(TDB_LIST_NODE*);
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
-#endif /* __TDBUTIL_H__ */
+#endif
diff --git a/source/lib/replace/system/network.h b/source/lib/replace/system/network.h
new file mode 100644
index 00000000000..5e648dcd156
--- /dev/null
+++ b/source/lib/replace/system/network.h
@@ -0,0 +1,113 @@
+#ifndef _system_network_h
+#define _system_network_h
+/*
+ Unix SMB/CIFS implementation.
+
+ networking system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_UNIXSOCKET
+#include <sys/un.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+/*
+ * The next three defines are needed to access the IPTOS_* options
+ * on some systems.
+ */
+
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_IP_H
+#include <netinet/in_ip.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef SOCKET_WRAPPER
+#ifndef SOCKET_WRAPPER_NOT_REPLACE
+#define SOCKET_WRAPPER_REPLACE
+#endif
+#include "lib/socket_wrapper/socket_wrapper.h"
+#endif
+
+#ifdef REPLACE_INET_NTOA
+char *rep_inet_ntoa(struct in_addr ip);
+#define inet_ntoa rep_inet_ntoa
+#endif
+
+/*
+ * glibc on linux doesn't seem to have MSG_WAITALL
+ * defined. I think the kernel has it though..
+ */
+#ifndef MSG_WAITALL
+#define MSG_WAITALL 0
+#endif
+
+/*
+ * Some older systems seem not to have MAXHOSTNAMELEN
+ * defined.
+ */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 254
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#endif
diff --git a/source/lib/replace/system/passwd.h b/source/lib/replace/system/passwd.h
new file mode 100644
index 00000000000..21f31f0388c
--- /dev/null
+++ b/source/lib/replace/system/passwd.h
@@ -0,0 +1,91 @@
+#ifndef _system_passwd_h
+#define _system_passwd_h
+
+/*
+ Unix SMB/CIFS implementation.
+
+ passwd system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_SYS_PRIV_H
+#include <sys/priv.h>
+#endif
+#ifdef HAVE_SYS_ID_H
+#include <sys/id.h>
+#endif
+
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+#ifdef HAVE_SYS_SECURITY_H
+#include <sys/security.h>
+#include <prot.h>
+#define PASSWORD_LENGTH 16
+#endif /* HAVE_SYS_SECURITY_H */
+
+#ifdef HAVE_GETPWANAM
+#include <sys/label.h>
+#include <sys/audit.h>
+#include <pwdadj.h>
+#endif
+
+#ifdef HAVE_COMPAT_H
+#include <compat.h>
+#endif
+
+#ifdef REPLACE_GETPASS
+#define getpass(prompt) getsmbpass((prompt))
+#endif
+
+#ifndef NGROUPS_MAX
+#define NGROUPS_MAX 32 /* Guess... */
+#endif
+
+/* what is the longest significant password available on your system?
+ Knowing this speeds up password searches a lot */
+#ifndef PASSWORD_LENGTH
+#define PASSWORD_LENGTH 8
+#endif
+
+#if defined(HAVE_PUTPRPWNAM) && defined(AUTH_CLEARTEXT_SEG_CHARS)
+#define OSF1_ENH_SEC 1
+#endif
+
+#ifndef ALLOW_CHANGE_PASSWORD
+#if (defined(HAVE_TERMIOS_H) && defined(HAVE_DUP2) && defined(HAVE_SETSID))
+#define ALLOW_CHANGE_PASSWORD 1
+#endif
+#endif
+
+#if defined(HAVE_CRYPT16) && defined(HAVE_GETAUTHUID)
+#define ULTRIX_AUTH 1
+#endif
+
+#endif
diff --git a/source/lib/replace/system/printing.h b/source/lib/replace/system/printing.h
new file mode 100644
index 00000000000..489ccb1da8c
--- /dev/null
+++ b/source/lib/replace/system/printing.h
@@ -0,0 +1,46 @@
+#ifndef _system_printing_h
+#define _system_printing_h
+
+/*
+ Unix SMB/CIFS implementation.
+
+ printing system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef AIX
+#define DEFAULT_PRINTING PRINT_AIX
+#define PRINTCAP_NAME "/etc/qconfig"
+#endif
+
+#ifdef HPUX
+#define DEFAULT_PRINTING PRINT_HPUX
+#endif
+
+#ifdef QNX
+#define DEFAULT_PRINTING PRINT_QNX
+#endif
+
+#ifndef DEFAULT_PRINTING
+#define DEFAULT_PRINTING PRINT_BSD
+#endif
+#ifndef PRINTCAP_NAME
+#define PRINTCAP_NAME "/etc/printcap"
+#endif
+
+#endif
diff --git a/source/lib/replace/system/readline.h b/source/lib/replace/system/readline.h
new file mode 100644
index 00000000000..4a64ef13766
--- /dev/null
+++ b/source/lib/replace/system/readline.h
@@ -0,0 +1,48 @@
+#ifndef _system_readline_h
+#define _system_readline_h
+/*
+ Unix SMB/CIFS implementation.
+
+ readline wrappers
+
+ 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.
+*/
+
+#ifdef HAVE_LIBREADLINE
+# ifdef HAVE_READLINE_READLINE_H
+# include <readline/readline.h>
+# ifdef HAVE_READLINE_HISTORY_H
+# include <readline/history.h>
+# endif
+# else
+# ifdef HAVE_READLINE_H
+# include <readline.h>
+# ifdef HAVE_HISTORY_H
+# include <history.h>
+# endif
+# else
+# undef HAVE_LIBREADLINE
+# endif
+# endif
+#endif
+
+#ifdef HAVE_NEW_LIBREADLINE
+# define RL_COMPLETION_CAST (rl_completion_func_t *)
+#else
+/* This type is missing from libreadline<4.0 (approximately) */
+# define RL_COMPLETION_CAST
+#endif /* HAVE_NEW_LIBREADLINE */
+
+#endif
diff --git a/source/lib/replace/system/select.h b/source/lib/replace/system/select.h
new file mode 100644
index 00000000000..20346259c27
--- /dev/null
+++ b/source/lib/replace/system/select.h
@@ -0,0 +1,33 @@
+#ifndef _system_select_h
+#define _system_select_h
+/*
+ Unix SMB/CIFS implementation.
+
+ select system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef SELECT_CAST
+#define SELECT_CAST
+#endif
+
+#endif
diff --git a/source/lib/replace/system/shmem.h b/source/lib/replace/system/shmem.h
new file mode 100644
index 00000000000..26fa7c8d433
--- /dev/null
+++ b/source/lib/replace/system/shmem.h
@@ -0,0 +1,55 @@
+#ifndef _system_shmem_h
+#define _system_shmem_h
+/*
+ Unix SMB/CIFS implementation.
+
+ shared memory system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#if defined(HAVE_SYS_IPC_H)
+#include <sys/ipc.h>
+#endif /* HAVE_SYS_IPC_H */
+
+#if defined(HAVE_SYS_SHM_H)
+#include <sys/shm.h>
+#endif /* HAVE_SYS_SHM_H */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+/* NetBSD doesn't have these */
+#ifndef SHM_R
+#define SHM_R 0400
+#endif
+
+#ifndef SHM_W
+#define SHM_W 0200
+#endif
+
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#endif
diff --git a/source/lib/replace/system/syslog.h b/source/lib/replace/system/syslog.h
new file mode 100644
index 00000000000..e123830a709
--- /dev/null
+++ b/source/lib/replace/system/syslog.h
@@ -0,0 +1,66 @@
+#ifndef _system_syslog_h
+#define _system_syslog_h
+/*
+ Unix SMB/CIFS implementation.
+
+ syslog system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#else
+#ifdef HAVE_SYS_SYSLOG_H
+#include <sys/syslog.h>
+#endif
+#endif
+
+/* For sys_adminlog(). */
+#ifndef LOG_EMERG
+#define LOG_EMERG 0 /* system is unusable */
+#endif
+
+#ifndef LOG_ALERT
+#define LOG_ALERT 1 /* action must be taken immediately */
+#endif
+
+#ifndef LOG_CRIT
+#define LOG_CRIT 2 /* critical conditions */
+#endif
+
+#ifndef LOG_ERR
+#define LOG_ERR 3 /* error conditions */
+#endif
+
+#ifndef LOG_WARNING
+#define LOG_WARNING 4 /* warning conditions */
+#endif
+
+#ifndef LOG_NOTICE
+#define LOG_NOTICE 5 /* normal but significant condition */
+#endif
+
+#ifndef LOG_INFO
+#define LOG_INFO 6 /* informational */
+#endif
+
+#ifndef LOG_DEBUG
+#define LOG_DEBUG 7 /* debug-level messages */
+#endif
+
+#endif
diff --git a/source/lib/replace/system/terminal.h b/source/lib/replace/system/terminal.h
new file mode 100644
index 00000000000..94d6b5cc98d
--- /dev/null
+++ b/source/lib/replace/system/terminal.h
@@ -0,0 +1,42 @@
+#ifndef _system_terminal_h
+#define _system_terminal_h
+/*
+ Unix SMB/CIFS implementation.
+
+ terminal system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef SUNOS4
+/* on SUNOS4 termios.h conflicts with sys/ioctl.h */
+#undef HAVE_TERMIOS_H
+#endif
+
+
+#if defined(HAVE_TERMIOS_H)
+/* POSIX terminal handling. */
+#include <termios.h>
+#elif defined(HAVE_TERMIO_H)
+/* Older SYSV terminal handling - don't use if we can avoid it. */
+#include <termio.h>
+#elif defined(HAVE_SYS_TERMIO_H)
+/* Older SYSV terminal handling - don't use if we can avoid it. */
+#include <sys/termio.h>
+#endif
+
+#endif
diff --git a/source/lib/replace/system/time.h b/source/lib/replace/system/time.h
new file mode 100644
index 00000000000..e7c88f133d4
--- /dev/null
+++ b/source/lib/replace/system/time.h
@@ -0,0 +1,40 @@
+#ifndef _system_time_h
+#define _system_time_h
+/*
+ Unix SMB/CIFS implementation.
+
+ time system include wrappers
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#endif
diff --git a/source/lib/replace1.c b/source/lib/replace/system/wait.h
index e1be56eb128..3855f7ae724 100644
--- a/source/lib/replace1.c
+++ b/source/lib/replace/system/wait.h
@@ -1,7 +1,11 @@
+#ifndef _system_wait_h
+#define _system_wait_h
/*
Unix SMB/CIFS implementation.
- replacement routines for broken systems
- Copyright (C) Andrew Tridgell 1992-1998
+
+ waitpid system include wrappers
+
+ Copyright (C) Andrew Tridgell 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
@@ -18,25 +22,22 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "includes.h"
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
- void replace1_dummy(void);
- void replace1_dummy(void) {}
+#include <signal.h>
-#ifndef HAVE_SETENV
- int setenv(const char *name, const char *value, int overwrite)
-{
- char *p = NULL;
- int ret = -1;
+#ifndef SIGCLD
+#define SIGCLD SIGCHLD
+#endif
- asprintf(&p, "%s=%s", name, value);
+#ifndef SIGNAL_CAST
+#define SIGNAL_CAST (RETSIGTYPE (*)(int))
+#endif
- if (overwrite || getenv(name)) {
- if (p) ret = putenv(p);
- } else {
- ret = 0;
- }
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
- return ret;
-}
#endif
diff --git a/source/lib/replace/test/os2_delete.c b/source/lib/replace/test/os2_delete.c
new file mode 100644
index 00000000000..c8abfccff9b
--- /dev/null
+++ b/source/lib/replace/test/os2_delete.c
@@ -0,0 +1,115 @@
+/*
+ test readdir/unlink pattern that OS/2 uses
+ tridge@samba.org July 2005
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+
+#define NUM_FILES 700
+#define READDIR_SIZE 100
+#define DELETE_SIZE 4
+
+#define TESTDIR "test.dir"
+
+static int test_readdir_os2_delete_ret;
+
+#define FAILED(d) (printf("failure: readdir [\nFailed for %s - %d = %s\n]\n", d, errno, strerror(errno)), test_readdir_os2_delete_ret = 1, 1)
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+static void cleanup(void)
+{
+ /* I'm a lazy bastard */
+ system("rm -rf " TESTDIR);
+ mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir");
+}
+
+static void create_files(void)
+{
+ int i;
+ for (i=0;i<NUM_FILES;i++) {
+ char fname[40];
+ sprintf(fname, TESTDIR "/test%u.txt", i);
+ close(open(fname, O_CREAT|O_RDWR, 0600)) == 0 || FAILED("close");
+ }
+}
+
+static int os2_delete(DIR *d)
+{
+ off_t offsets[READDIR_SIZE];
+ int i, j;
+ struct dirent *de;
+ char names[READDIR_SIZE][30];
+
+ /* scan, remembering offsets */
+ for (i=0, de=readdir(d);
+ de && i < READDIR_SIZE;
+ de=readdir(d), i++) {
+ offsets[i] = telldir(d);
+ strcpy(names[i], de->d_name);
+ }
+
+ if (i == 0) {
+ return 0;
+ }
+
+ /* delete the first few */
+ for (j=0; j<MIN(i, DELETE_SIZE); j++) {
+ char fname[40];
+ sprintf(fname, TESTDIR "/%s", names[j]);
+ unlink(fname) == 0 || FAILED("unlink");
+ }
+
+ /* seek to just after the deletion */
+ seekdir(d, offsets[j-1]);
+
+ /* return number deleted */
+ return j;
+}
+
+int test_readdir_os2_delete(void)
+{
+ int total_deleted = 0;
+ DIR *d;
+ struct dirent *de;
+
+ test_readdir_os2_delete_ret = 0;
+
+ cleanup();
+ create_files();
+
+ d = opendir(TESTDIR "/test0.txt");
+ if (d != NULL) FAILED("opendir() on file succeed");
+ if (errno != ENOTDIR) FAILED("opendir() on file didn't give ENOTDIR");
+
+ d = opendir(TESTDIR);
+
+ /* skip past . and .. */
+ de = readdir(d);
+ strcmp(de->d_name, ".") == 0 || FAILED("match .");
+ de = readdir(d);
+ strcmp(de->d_name, "..") == 0 || FAILED("match ..");
+
+ while (1) {
+ int n = os2_delete(d);
+ if (n == 0) break;
+ total_deleted += n;
+ }
+ closedir(d);
+
+ fprintf(stderr, "Deleted %d files of %d\n", total_deleted, NUM_FILES);
+
+ rmdir(TESTDIR) == 0 || FAILED("rmdir");
+
+ return test_readdir_os2_delete_ret;
+}
diff --git a/source/lib/replace/test/shared_mmap.c b/source/lib/replace/test/shared_mmap.c
new file mode 100644
index 00000000000..50dad8d6964
--- /dev/null
+++ b/source/lib/replace/test/shared_mmap.c
@@ -0,0 +1,68 @@
+/* this tests whether we can use a shared writeable mmap on a file -
+ as needed for the mmap variant of FAST_SHARE_MODES */
+
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define DATA "conftest.mmap"
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+main()
+{
+ int *buf;
+ int i;
+ int fd = open(DATA,O_RDWR|O_CREAT|O_TRUNC,0666);
+ int count=7;
+
+ if (fd == -1) exit(1);
+
+ for (i=0;i<10000;i++) {
+ write(fd,&i,sizeof(i));
+ }
+
+ close(fd);
+
+ if (fork() == 0) {
+ fd = open(DATA,O_RDWR);
+ if (fd == -1) exit(1);
+
+ buf = (int *)mmap(NULL, 10000*sizeof(int),
+ (PROT_READ | PROT_WRITE),
+ MAP_FILE | MAP_SHARED,
+ fd, 0);
+
+ while (count-- && buf[9124] != 55732) sleep(1);
+
+ if (count <= 0) exit(1);
+
+ buf[1763] = 7268;
+ exit(0);
+ }
+
+ fd = open(DATA,O_RDWR);
+ if (fd == -1) exit(1);
+
+ buf = (int *)mmap(NULL, 10000*sizeof(int),
+ (PROT_READ | PROT_WRITE),
+ MAP_FILE | MAP_SHARED,
+ fd, 0);
+
+ if (buf == (int *)-1) exit(1);
+
+ buf[9124] = 55732;
+
+ while (count-- && buf[1763] != 7268) sleep(1);
+
+ unlink(DATA);
+
+ if (count > 0) exit(0);
+ exit(1);
+}
diff --git a/source/lib/replace/test/testsuite.c b/source/lib/replace/test/testsuite.c
new file mode 100644
index 00000000000..effbdb13ef0
--- /dev/null
+++ b/source/lib/replace/test/testsuite.c
@@ -0,0 +1,481 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libreplace tests
+
+ Copyright (C) Jelmer Vernooij 2006
+
+ ** NOTE! The following LGPL license applies to the talloc
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "replace.h"
+
+/*
+ we include all the system/ include files here so that libreplace tests
+ them in the build farm
+*/
+#include "system/capability.h"
+#include "system/dir.h"
+#include "system/filesys.h"
+#include "system/glob.h"
+#include "system/iconv.h"
+#include "system/locale.h"
+#include "system/network.h"
+#include "system/passwd.h"
+#include "system/printing.h"
+#include "system/readline.h"
+#include "system/select.h"
+#include "system/shmem.h"
+#include "system/syslog.h"
+#include "system/terminal.h"
+#include "system/time.h"
+#include "system/wait.h"
+#include "system/aio.h"
+
+#define TESTFILE "testfile.dat"
+
+/*
+ test ftruncate() function
+ */
+static int test_ftruncate(void)
+{
+ struct stat st;
+ int fd;
+ const int size = 1234;
+ printf("test: ftruncate\n");
+ unlink(TESTFILE);
+ fd = open(TESTFILE, O_RDWR|O_CREAT, 0600);
+ if (fd == -1) {
+ printf("failure: ftruncate [\n"
+ "creating '%s' failed - %s\n]\n", TESTFILE, strerror(errno));
+ return false;
+ }
+ if (ftruncate(fd, size) != 0) {
+ printf("failure: ftruncate [\n%s\n]\n", strerror(errno));
+ return false;
+ }
+ if (fstat(fd, &st) != 0) {
+ printf("failure: ftruncate [\nfstat failed - %s\n]\n", strerror(errno));
+ return false;
+ }
+ if (st.st_size != size) {
+ printf("failure: ftruncate [\ngave wrong size %d - expected %d\n]\n",
+ (int)st.st_size, size);
+ return false;
+ }
+ unlink(TESTFILE);
+ printf("success: ftruncate\n");
+ return true;
+}
+
+/*
+ test strlcpy() function.
+ see http://www.gratisoft.us/todd/papers/strlcpy.html
+ */
+static int test_strlcpy(void)
+{
+ char buf[4];
+ const struct {
+ const char *src;
+ size_t result;
+ } tests[] = {
+ { "abc", 3 },
+ { "abcdef", 6 },
+ { "abcd", 4 },
+ { "", 0 },
+ { NULL, 0 }
+ };
+ int i;
+ printf("test: strlcpy\n");
+ for (i=0;tests[i].src;i++) {
+ if (strlcpy(buf, tests[i].src, sizeof(buf)) != tests[i].result) {
+ printf("failure: strlcpy [\ntest %d failed\n]\n", i);
+ return false;
+ }
+ }
+ printf("success: strlcpy\n");
+ return true;
+}
+
+static int test_strlcat(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_mktime(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_innetgr(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_initgroups(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_memmove(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_strdup(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_setlinebuf(void)
+{
+ printf("test: setlinebuf\n");
+ setlinebuf(stdout);
+ printf("success: setlinebuf\n");
+ return true;
+}
+
+static int test_vsyslog(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_timegm(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_setenv(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_strndup(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_strnlen(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_waitpid(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_seteuid(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_setegid(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_asprintf(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_snprintf(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_vasprintf(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_vsnprintf(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_opendir(void)
+{
+ /* FIXME */
+ return true;
+}
+
+extern int test_readdir_os2_delete(void);
+
+static int test_readdir(void)
+{
+ printf("test: readdir\n");
+ if (test_readdir_os2_delete() != 0) {
+ return false;
+ }
+ printf("success: readdir\n");
+ return true;
+}
+
+static int test_telldir(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_seekdir(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_dlopen(void)
+{
+ /* FIXME: test dlopen, dlsym, dlclose, dlerror */
+ return true;
+}
+
+
+static int test_chroot(void)
+{
+ /* FIXME: chroot() */
+ return true;
+}
+
+static int test_bzero(void)
+{
+ /* FIXME: bzero */
+ return true;
+}
+
+static int test_strerror(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_errno(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_mkdtemp(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_mkstemp(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_pread(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_pwrite(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_getpass(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_inet_ntoa(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_strtoll(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_strtoull(void)
+{
+ /* FIXME */
+ return true;
+}
+
+/*
+FIXME:
+Types:
+bool
+socklen_t
+uint_t
+uint{8,16,32,64}_t
+int{8,16,32,64}_t
+intptr_t
+
+Constants:
+PATH_NAME_MAX
+UINT{16,32,64}_MAX
+INT32_MAX
+*/
+
+static int test_va_copy(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_FUNCTION(void)
+{
+ /* FIXME: test __FUNCTION__ macro */
+ return true;
+}
+
+static int test_MIN(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_MAX(void)
+{
+ /* FIXME */
+ return true;
+}
+
+static int test_socketpair(void)
+{
+ int sock[2];
+ char buf[20];
+
+ printf("test: socketpair\n");
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == -1) {
+ printf("failure: socketpair [\n"
+ "socketpair() failed\n"
+ "]\n");
+ return false;
+ }
+
+ if (write(sock[1], "automatisch", 12) == -1) {
+ printf("failure: socketpair [\n"
+ "write() failed: %s\n"
+ "]\n", strerror(errno));
+ return false;
+ }
+
+ if (read(sock[0], buf, 12) == -1) {
+ printf("failure: socketpair [\n"
+ "read() failed: %s\n"
+ "]\n", strerror(errno));
+ return false;
+ }
+
+ if (strcmp(buf, "automatisch") != 0) {
+ printf("failure: socketpair [\n"
+ "expected: automatisch, got: %s\n"
+ "]\n", buf);
+ return false;
+ }
+
+ printf("success: socketpair\n");
+
+ return true;
+}
+
+struct torture_context;
+bool torture_local_replace(struct torture_context *ctx)
+{
+ bool ret = true;
+ ret &= test_ftruncate();
+ ret &= test_strlcpy();
+ ret &= test_strlcat();
+ ret &= test_mktime();
+ ret &= test_innetgr();
+ ret &= test_initgroups();
+ ret &= test_memmove();
+ ret &= test_strdup();
+ ret &= test_setlinebuf();
+ ret &= test_vsyslog();
+ ret &= test_timegm();
+ ret &= test_setenv();
+ ret &= test_strndup();
+ ret &= test_strnlen();
+ ret &= test_waitpid();
+ ret &= test_seteuid();
+ ret &= test_setegid();
+ ret &= test_asprintf();
+ ret &= test_snprintf();
+ ret &= test_vasprintf();
+ ret &= test_vsnprintf();
+ ret &= test_opendir();
+ ret &= test_readdir();
+ ret &= test_telldir();
+ ret &= test_seekdir();
+ ret &= test_dlopen();
+ ret &= test_chroot();
+ ret &= test_bzero();
+ ret &= test_strerror();
+ ret &= test_errno();
+ ret &= test_mkdtemp();
+ ret &= test_mkstemp();
+ ret &= test_pread();
+ ret &= test_pwrite();
+ ret &= test_getpass();
+ ret &= test_inet_ntoa();
+ ret &= test_strtoll();
+ ret &= test_strtoll();
+ ret &= test_strtoull();
+ ret &= test_va_copy();
+ ret &= test_FUNCTION();
+ ret &= test_MIN();
+ ret &= test_MAX();
+ ret &= test_socketpair();
+
+ return ret;
+}
+
+#if _SAMBA_BUILD_<4
+int main(void)
+{
+ bool ret = torture_local_replace(NULL);
+ if (ret)
+ return 0;
+ return -1;
+}
+#endif
diff --git a/source/lib/timegm.c b/source/lib/replace/timegm.c
index dcc710b1ece..395c684e117 100644
--- a/source/lib/timegm.c
+++ b/source/lib/replace/timegm.c
@@ -35,9 +35,8 @@
adapted for Samba4 by Andrew Tridgell
*/
-#include "includes.h"
-
-#ifndef HAVE_TIMEGM
+#include "replace.h"
+#include "system/time.h"
static int is_leap(unsigned y)
{
@@ -45,14 +44,14 @@ static int is_leap(unsigned y)
return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
}
-time_t timegm(struct tm *tm)
+time_t rep_timegm(struct tm *tm)
{
static const unsigned ndays[2][12] ={
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
time_t res = 0;
unsigned i;
-
+
if (tm->tm_mon > 12 ||
tm->tm_mon < 0 ||
tm->tm_mday > 31 ||
@@ -62,7 +61,7 @@ time_t timegm(struct tm *tm)
/* invalid tm structure */
return 0;
}
-
+
for (i = 70; i < tm->tm_year; ++i)
res += is_leap(i) ? 366 : 365;
@@ -77,5 +76,3 @@ time_t timegm(struct tm *tm)
res += tm->tm_sec;
return res;
}
-
-#endif /* HAVE_TIMEGM */
diff --git a/source/lib/replace/timegm.m4 b/source/lib/replace/timegm.m4
new file mode 100644
index 00000000000..59f3ae05211
--- /dev/null
+++ b/source/lib/replace/timegm.m4
@@ -0,0 +1 @@
+AC_CHECK_FUNCS(timegm,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} timegm.o"])
diff --git a/source/lib/replace/win32.m4 b/source/lib/replace/win32.m4
new file mode 100644
index 00000000000..9ac84cdf2ad
--- /dev/null
+++ b/source/lib/replace/win32.m4
@@ -0,0 +1,20 @@
+AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h)
+
+#######################################
+# Check for mkdir mode
+AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode,
+ AC_TRY_COMPILE([
+ #include <stdio.h>
+ #ifdef HAVE_DIRECT_H
+ #include <direct.h>
+ #endif],[
+ mkdir("foo",0777);
+ return 0;
+ ],
+ ac_mkdir_has_mode="yes",
+ ac_mkdir_has_mode="no") )
+
+if test "$ac_mkdir_has_mode" = "yes"
+then
+ AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option])
+fi
diff --git a/source/lib/replace/win32_replace.h b/source/lib/replace/win32_replace.h
new file mode 100644
index 00000000000..9901e72f6ef
--- /dev/null
+++ b/source/lib/replace/win32_replace.h
@@ -0,0 +1,159 @@
+#ifndef _WIN32_REPLACE_H
+#define _WIN32_REPLACE_H
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+/* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */
+
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define ECONNREFUSED WSAECONNREFUSED
+#define EINPROGRESS WSAEINPROGRESS
+#define EMSGSIZE WSAEMSGSIZE
+#define ENOBUFS WSAENOBUFS
+#define ENOTSOCK WSAENOTSOCK
+#define ENETUNREACH WSAENETUNREACH
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define ENOTCONN WSAENOTCONN
+#define ENOTSUP 134
+
+/* We undefine the following constants due to conflicts with the w32api headers
+ * and the Windows Platform SDK/DDK.
+ */
+
+#undef interface
+
+#undef ERROR_INVALID_PARAMETER
+#undef ERROR_INSUFFICIENT_BUFFER
+#undef ERROR_INVALID_DATATYPE
+
+#undef FILE_GENERIC_READ
+#undef FILE_GENERIC_WRITE
+#undef FILE_GENERIC_EXECUTE
+#undef FILE_ATTRIBUTE_READONLY
+#undef FILE_ATTRIBUTE_HIDDEN
+#undef FILE_ATTRIBUTE_SYSTEM
+#undef FILE_ATTRIBUTE_DIRECTORY
+#undef FILE_ATTRIBUTE_ARCHIVE
+#undef FILE_ATTRIBUTE_DEVICE
+#undef FILE_ATTRIBUTE_NORMAL
+#undef FILE_ATTRIBUTE_TEMPORARY
+#undef FILE_ATTRIBUTE_REPARSE_POINT
+#undef FILE_ATTRIBUTE_COMPRESSED
+#undef FILE_ATTRIBUTE_OFFLINE
+#undef FILE_ATTRIBUTE_ENCRYPTED
+#undef FILE_FLAG_WRITE_THROUGH
+#undef FILE_FLAG_NO_BUFFERING
+#undef FILE_FLAG_RANDOM_ACCESS
+#undef FILE_FLAG_SEQUENTIAL_SCAN
+#undef FILE_FLAG_DELETE_ON_CLOSE
+#undef FILE_FLAG_BACKUP_SEMANTICS
+#undef FILE_FLAG_POSIX_SEMANTICS
+#undef FILE_TYPE_DISK
+#undef FILE_TYPE_UNKNOWN
+#undef FILE_CASE_SENSITIVE_SEARCH
+#undef FILE_CASE_PRESERVED_NAMES
+#undef FILE_UNICODE_ON_DISK
+#undef FILE_PERSISTENT_ACLS
+#undef FILE_FILE_COMPRESSION
+#undef FILE_VOLUME_QUOTAS
+#undef FILE_VOLUME_IS_COMPRESSED
+#undef FILE_NOTIFY_CHANGE_FILE_NAME
+#undef FILE_NOTIFY_CHANGE_DIR_NAME
+#undef FILE_NOTIFY_CHANGE_ATTRIBUTES
+#undef FILE_NOTIFY_CHANGE_SIZE
+#undef FILE_NOTIFY_CHANGE_LAST_WRITE
+#undef FILE_NOTIFY_CHANGE_LAST_ACCESS
+#undef FILE_NOTIFY_CHANGE_CREATION
+#undef FILE_NOTIFY_CHANGE_EA
+#undef FILE_NOTIFY_CHANGE_SECURITY
+#undef FILE_NOTIFY_CHANGE_STREAM_NAME
+#undef FILE_NOTIFY_CHANGE_STREAM_SIZE
+#undef FILE_NOTIFY_CHANGE_STREAM_WRITE
+#undef FILE_NOTIFY_CHANGE_NAME
+
+#undef PRINTER_ATTRIBUTE_QUEUED
+#undef PRINTER_ATTRIBUTE_DIRECT
+#undef PRINTER_ATTRIBUTE_DEFAULT
+#undef PRINTER_ATTRIBUTE_SHARED
+#undef PRINTER_ATTRIBUTE_NETWORK
+#undef PRINTER_ATTRIBUTE_HIDDEN
+#undef PRINTER_ATTRIBUTE_LOCAL
+#undef PRINTER_ATTRIBUTE_ENABLE_DEVQ
+#undef PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
+#undef PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
+#undef PRINTER_ATTRIBUTE_WORK_OFFLINE
+#undef PRINTER_ATTRIBUTE_ENABLE_BIDI
+#undef PRINTER_ATTRIBUTE_RAW_ONLY
+#undef PRINTER_ATTRIBUTE_PUBLISHED
+#undef PRINTER_ENUM_DEFAULT
+#undef PRINTER_ENUM_LOCAL
+#undef PRINTER_ENUM_CONNECTIONS
+#undef PRINTER_ENUM_FAVORITE
+#undef PRINTER_ENUM_NAME
+#undef PRINTER_ENUM_REMOTE
+#undef PRINTER_ENUM_SHARED
+#undef PRINTER_ENUM_NETWORK
+#undef PRINTER_ENUM_EXPAND
+#undef PRINTER_ENUM_CONTAINER
+#undef PRINTER_ENUM_ICON1
+#undef PRINTER_ENUM_ICON2
+#undef PRINTER_ENUM_ICON3
+#undef PRINTER_ENUM_ICON4
+#undef PRINTER_ENUM_ICON5
+#undef PRINTER_ENUM_ICON6
+#undef PRINTER_ENUM_ICON7
+#undef PRINTER_ENUM_ICON8
+#undef PRINTER_STATUS_PAUSED
+#undef PRINTER_STATUS_ERROR
+#undef PRINTER_STATUS_PENDING_DELETION
+#undef PRINTER_STATUS_PAPER_JAM
+#undef PRINTER_STATUS_PAPER_OUT
+#undef PRINTER_STATUS_MANUAL_FEED
+#undef PRINTER_STATUS_PAPER_PROBLEM
+#undef PRINTER_STATUS_OFFLINE
+#undef PRINTER_STATUS_IO_ACTIVE
+#undef PRINTER_STATUS_BUSY
+#undef PRINTER_STATUS_PRINTING
+#undef PRINTER_STATUS_OUTPUT_BIN_FULL
+#undef PRINTER_STATUS_NOT_AVAILABLE
+#undef PRINTER_STATUS_WAITING
+#undef PRINTER_STATUS_PROCESSING
+#undef PRINTER_STATUS_INITIALIZING
+#undef PRINTER_STATUS_WARMING_UP
+#undef PRINTER_STATUS_TONER_LOW
+#undef PRINTER_STATUS_NO_TONER
+#undef PRINTER_STATUS_PAGE_PUNT
+#undef PRINTER_STATUS_USER_INTERVENTION
+#undef PRINTER_STATUS_OUT_OF_MEMORY
+#undef PRINTER_STATUS_DOOR_OPEN
+#undef PRINTER_STATUS_SERVER_UNKNOWN
+#undef PRINTER_STATUS_POWER_SAVE
+
+#undef DWORD
+#undef HKEY_CLASSES_ROOT
+#undef HKEY_CURRENT_USER
+#undef HKEY_LOCAL_MACHINE
+#undef HKEY_USERS
+#undef HKEY_PERFORMANCE_DATA
+#undef HKEY_CURRENT_CONFIG
+#undef HKEY_DYN_DATA
+#undef REG_DWORD
+#undef REG_QWORD
+
+#undef SERVICE_STATE_ALL
+
+#undef SE_GROUP_MANDATORY
+#undef SE_GROUP_ENABLED_BY_DEFAULT
+#undef SE_GROUP_ENABLED
+
+#endif /* _WIN32_REPLACE_H */
diff --git a/source/lib/secace.c b/source/lib/secace.c
index f1d4d99cc16..ab7ad811a0a 100644
--- a/source/lib/secace.c
+++ b/source/lib/secace.c
@@ -46,10 +46,10 @@ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
ace_dest->type = ace_src->type;
ace_dest->flags = ace_src->flags;
ace_dest->size = ace_src->size;
- ace_dest->info.mask = ace_src->info.mask;
+ ace_dest->access_mask = ace_src->access_mask;
ace_dest->obj_flags = ace_src->obj_flags;
- memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct uuid));
- memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct uuid));
+ memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct GUID));
+ memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct GUID));
sid_copy(&ace_dest->trustee, &ace_src->trustee);
}
@@ -62,7 +62,7 @@ void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, u
t->type = type;
t->flags = flag;
t->size = sid_size(sid) + 8;
- t->info = mask;
+ t->access_mask = mask;
ZERO_STRUCTP(&t->trustee);
sid_copy(&t->trustee, sid);
@@ -89,7 +89,7 @@ NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsign
(*pp_new)[i].type = 0;
(*pp_new)[i].flags = 0;
(*pp_new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid);
- (*pp_new)[i].info.mask = mask;
+ (*pp_new)[i].access_mask = mask;
sid_copy(&(*pp_new)[i].trustee, sid);
return NT_STATUS_OK;
}
@@ -106,7 +106,7 @@ NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
for (i = 0; i < num; i ++) {
if (sid_compare(&ace[i].trustee, sid) == 0) {
- ace[i].info.mask = mask;
+ ace[i].access_mask = mask;
return NT_STATUS_OK;
}
}
@@ -160,7 +160,7 @@ BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
/* Check top level stuff */
if (s1->type != s2->type || s1->flags != s2->flags ||
- s1->info.mask != s2->info.mask) {
+ s1->access_mask != s2->access_mask) {
return False;
}
diff --git a/source/lib/secacl.c b/source/lib/secacl.c
index e213e0d9a0c..4e2178c195e 100644
--- a/source/lib/secacl.c
+++ b/source/lib/secacl.c
@@ -46,13 +46,13 @@ SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *a
positive number. */
if ((num_aces) &&
- ((dst->ace = TALLOC_ARRAY(ctx, SEC_ACE, num_aces))
+ ((dst->aces = TALLOC_ARRAY(ctx, SEC_ACE, num_aces))
== NULL)) {
return NULL;
}
for (i = 0; i < num_aces; i++) {
- dst->ace[i] = ace_list[i]; /* Structure copy. */
+ dst->aces[i] = ace_list[i]; /* Structure copy. */
dst->size += ace_list[i].size;
}
@@ -68,7 +68,7 @@ SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
if(src == NULL)
return NULL;
- return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
+ return make_sec_acl(ctx, src->revision, src->num_aces, src->aces);
}
/*******************************************************************
@@ -105,7 +105,7 @@ BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
BOOL found = False;
for (j = 0; j < s2->num_aces; j++) {
- if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
+ if (sec_ace_equal(&s1->aces[i], &s2->aces[j])) {
found = True;
break;
}
diff --git a/source/lib/secdesc.c b/source/lib/secdesc.c
index f8873277cf8..16dde0da111 100644
--- a/source/lib/secdesc.c
+++ b/source/lib/secdesc.c
@@ -49,8 +49,8 @@ size_t sec_desc_size(SEC_DESC *psd)
if (psd->owner_sid != NULL)
offset += sid_size(psd->owner_sid);
- if (psd->grp_sid != NULL)
- offset += sid_size(psd->grp_sid);
+ if (psd->group_sid != NULL)
+ offset += sid_size(psd->group_sid);
if (psd->sacl != NULL)
offset += psd->sacl->size;
@@ -104,11 +104,11 @@ BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
return False;
}
- if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
+ if (!sid_equal(s1->group_sid, s2->group_sid)) {
fstring str1, str2;
- sid_to_string(str1, s1->grp_sid);
- sid_to_string(str2, s2->grp_sid);
+ sid_to_string(str1, s1->group_sid);
+ sid_to_string(str2, s2->group_sid);
DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
str1, str2));
@@ -157,8 +157,8 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU
owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
old_sdb->sec->owner_sid;
- group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
- old_sdb->sec->grp_sid;
+ group_sid = new_sdb->sec->group_sid ? new_sdb->sec->group_sid :
+ old_sdb->sec->group_sid;
secdesc_type = new_sdb->sec->type;
@@ -192,7 +192,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,
- const DOM_SID *owner_sid, const DOM_SID *grp_sid,
+ const DOM_SID *owner_sid, const DOM_SID *group_sid,
SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
{
SEC_DESC *dst;
@@ -219,7 +219,7 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
goto error_exit;
- if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
+ if(group_sid && ((dst->group_sid = sid_dup_talloc(ctx,group_sid)) == NULL))
goto error_exit;
if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
@@ -248,9 +248,9 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
offset += sid_size(dst->owner_sid);
}
- if (dst->grp_sid != NULL) {
+ if (dst->group_sid != NULL) {
dst->off_grp_sid = offset;
- offset += sid_size(dst->grp_sid);
+ offset += sid_size(dst->group_sid);
}
*sd_size = (size_t)offset;
@@ -274,7 +274,7 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
return NULL;
return make_sec_desc( ctx, src->revision, src->type,
- src->owner_sid, src->grp_sid, src->sacl,
+ src->owner_sid, src->group_sid, src->sacl,
src->dacl, &dummy);
}
@@ -282,11 +282,11 @@ 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, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
+SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *group_sid,
SEC_ACL *dacl, size_t *sd_size)
{
return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
- owner_sid, grp_sid, NULL, dacl, sd_size);
+ owner_sid, group_sid, NULL, dacl, sd_size);
}
/*******************************************************************
@@ -341,7 +341,7 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
*sd_size = 0;
- status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
+ status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
if (!NT_STATUS_IS_OK(status))
return status;
@@ -350,7 +350,7 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
return NT_STATUS_UNSUCCESSFUL;
if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
- psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
+ psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
return NT_STATUS_UNSUCCESSFUL;
*psd = sd;
@@ -369,7 +369,7 @@ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
if (!sd || !sid)
return NT_STATUS_INVALID_PARAMETER;
- status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
+ status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
if (!NT_STATUS_IS_OK(status))
return status;
@@ -393,7 +393,7 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
*sd_size = 0;
- status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
+ status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
if (!NT_STATUS_IS_OK(status))
return status;
@@ -402,7 +402,7 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
return NT_STATUS_UNSUCCESSFUL;
if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
- psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
+ psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
return NT_STATUS_UNSUCCESSFUL;
*psd = sd;
@@ -434,7 +434,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
return NULL;
for (i = 0; i < the_acl->num_aces; i++) {
- SEC_ACE *ace = &the_acl->ace[i];
+ SEC_ACE *ace = &the_acl->aces[i];
SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
uint8 new_flags = 0;
BOOL inherit = False;
@@ -490,17 +490,17 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
if (!inherit)
continue;
- init_sec_access(&new_ace->info, ace->info.mask);
+ init_sec_access(&new_ace->access_mask, ace->access_mask);
init_sec_ace(new_ace, &ace->trustee, ace->type,
- new_ace->info, new_flags);
+ new_ace->access_mask, new_flags);
sid_to_string(sid_str, &ace->trustee);
DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
" inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
- ace->type, ace->flags, ace->info.mask,
+ ace->type, ace->flags, ace->access_mask,
sid_str, new_ace->type, new_ace->flags,
- new_ace->info.mask));
+ new_ace->access_mask));
new_ace_list_ndx++;
}
@@ -515,7 +515,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
parent_ctr->owner_sid,
- parent_ctr->grp_sid,
+ parent_ctr->group_sid,
parent_ctr->sacl,
new_dacl, &size);
@@ -530,7 +530,5 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
void init_sec_access(SEC_ACCESS *t, uint32 mask)
{
- t->mask = mask;
+ *t = mask;
}
-
-
diff --git a/source/lib/sharesec.c b/source/lib/sharesec.c
index 8105d5c37a6..e3216aa4594 100644
--- a/source/lib/sharesec.c
+++ b/source/lib/sharesec.c
@@ -108,7 +108,8 @@ SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def
Pull a security descriptor from the share tdb.
********************************************************************/
-SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
+SEC_DESC *get_share_security( TALLOC_CTX *ctx, const char *servicename,
+ size_t *psize)
{
prs_struct ps;
fstring key;
@@ -122,12 +123,13 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
/* Fetch security descriptor from tdb */
- slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", servicename);
if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 ||
!sec_io_desc("get_share_security", &psd, &ps, 1)) {
- DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) ));
+ DEBUG(4, ("get_share_security: using default secdesc for %s\n",
+ servicename));
return get_share_security_default(ctx, psize, GENERIC_ALL_ACCESS);
}
@@ -143,7 +145,7 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
Store a security descriptor in the share db.
********************************************************************/
-BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
+BOOL set_share_security(const char *share_name, SEC_DESC *psd)
{
prs_struct ps;
TALLOC_CTX *mem_ctx = NULL;
@@ -186,24 +188,56 @@ out:
Delete a security descriptor.
********************************************************************/
-BOOL delete_share_security(int snum)
+BOOL delete_share_security(const struct share_params *params)
{
TDB_DATA kbuf;
fstring key;
- slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+ slprintf(key, sizeof(key)-1, "SECDESC/%s",
+ lp_servicename(params->service));
kbuf.dptr = key;
kbuf.dsize = strlen(key)+1;
- if (tdb_delete(share_tdb, kbuf) != 0) {
+ if (tdb_trans_delete(share_tdb, kbuf) != 0) {
DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
- lp_servicename(snum) ));
+ lp_servicename(params->service) ));
return False;
}
return True;
}
+/*******************************************************************
+ Can this user access with share with the required permissions ?
+********************************************************************/
+
+BOOL share_access_check(const NT_USER_TOKEN *token, const char *sharename,
+ uint32 desired_access)
+{
+ uint32 granted;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = NULL;
+ SEC_DESC *psd = NULL;
+ size_t sd_size;
+ BOOL ret = True;
+
+ if (!(mem_ctx = talloc_init("share_access_check"))) {
+ return False;
+ }
+
+ psd = get_share_security(mem_ctx, sharename, &sd_size);
+
+ if (!psd) {
+ TALLOC_FREE(mem_ctx);
+ return True;
+ }
+
+ ret = se_access_check(psd, token, desired_access, &granted, &status);
+
+ talloc_destroy(mem_ctx);
+ return ret;
+}
+
/***************************************************************************
Parse the contents of an acl string from a usershare file.
***************************************************************************/
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index a63e1c1bcc3..c102c2185f5 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -340,8 +340,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
return result;
}
- static int ldapmsg_destructor(void *p) {
- LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *);
+ static int ldapmsg_destructor(LDAPMessage **result) {
ldap_msgfree(*result);
return 0;
}
@@ -361,9 +360,8 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
talloc_set_destructor(handle, ldapmsg_destructor);
}
- static int ldapmod_destructor(void *p) {
- LDAPMod ***result = talloc_get_type_abort(p, LDAPMod **);
- ldap_mods_free(*result, True);
+ static int ldapmod_destructor(LDAPMod ***mod) {
+ ldap_mods_free(*mod, True);
return 0;
}
@@ -574,7 +572,6 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
{
struct smbldap_state *tmp_ldap_state;
struct smbldap_state_lookup *t;
- struct smbldap_state_lookup *tmp;
if ((tmp_ldap_state = smbldap_find_state(ld))) {
SMB_ASSERT(tmp_ldap_state == smbldap_state);
@@ -584,7 +581,7 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
t = SMB_XMALLOC_P(struct smbldap_state_lookup);
ZERO_STRUCTP(t);
- DLIST_ADD_END(smbldap_state_lookup_list, t, tmp);
+ DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
t->ld = ld;
t->smbldap_state = smbldap_state;
}
@@ -806,20 +803,27 @@ static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
if (freeit) {
SAFE_FREE(*whop);
- memset(*credp, '\0', strlen(*credp));
+ if (*credp) {
+ memset(*credp, '\0', strlen(*credp));
+ }
SAFE_FREE(*credp);
} else {
DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
- ldap_state->bind_dn));
+ ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
- *whop = SMB_STRDUP(ldap_state->bind_dn);
- if (!*whop) {
- return LDAP_NO_MEMORY;
- }
- *credp = SMB_STRDUP(ldap_state->bind_secret);
- if (!*credp) {
- SAFE_FREE(*whop);
- return LDAP_NO_MEMORY;
+ if (ldap_state->anonymous) {
+ *whop = NULL;
+ *credp = NULL;
+ } else {
+ *whop = SMB_STRDUP(ldap_state->bind_dn);
+ if (!*whop) {
+ return LDAP_NO_MEMORY;
+ }
+ *credp = SMB_STRDUP(ldap_state->bind_secret);
+ if (!*credp) {
+ SAFE_FREE(*whop);
+ return LDAP_NO_MEMORY;
+ }
}
*methodp = LDAP_AUTH_SIMPLE;
}
@@ -841,12 +845,13 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct,
ber_tag_t request,
ber_int_t msgid, void *arg)
{
- struct smbldap_state *ldap_state = arg;
+ struct smbldap_state *ldap_state =
+ (struct smbldap_state *)arg;
int rc;
int version;
DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
- url, ldap_state->bind_dn));
+ url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
/* call START_TLS again (ldaps:// is handled by the OpenLDAP library
* itself) before rebinding to another LDAP server to avoid to expose
@@ -927,24 +932,22 @@ static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct)
{
int rc;
- char *ldap_dn;
- char *ldap_secret;
int version;
- /* get the password */
- if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) {
- DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
- return LDAP_INVALID_CREDENTIALS;
- }
+ if (!ldap_state->anonymous && !ldap_state->bind_dn) {
- ldap_state->bind_dn = ldap_dn;
- ldap_state->bind_secret = ldap_secret;
+ /* get the default dn and password only if they are not set already */
+ if (!fetch_ldap_pw(&ldap_state->bind_dn, &ldap_state->bind_secret)) {
+ DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
+ return LDAP_INVALID_CREDENTIALS;
+ }
+ }
/* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
(OpenLDAP) doesnt' seem to support it */
DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
- ldap_state->uri, ldap_dn));
+ ldap_state->uri, ldap_state->bind_dn));
#ifdef HAVE_LDAP_SET_REBIND_PROC
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
@@ -964,7 +967,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
#endif
- rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
+ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
@@ -973,7 +976,8 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
DEBUG(ldap_state->num_failures ? 2 : 0,
("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
ldap_state->uri,
- ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc),
+ ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
+ ldap_err2string(rc),
ld_error ? ld_error : "(unknown)"));
SAFE_FREE(ld_error);
ldap_state->num_failures++;
@@ -1080,8 +1084,6 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
DEBUG(5,("The connection to the LDAP server was closed\n"));
/* maybe free the results here --metze */
-
-
return NT_STATUS_OK;
}
@@ -1230,12 +1232,23 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
sizelimit, res);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
+ int ld_errno;
+
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
ldap_get_option(ldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(10,("Failed search for base: %s, error: %s "
- "(%s)\n", base, ldap_err2string(rc),
- ld_error ? ld_error : "unknown"));
+ DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
+ "(%s)\n", base, ld_errno,
+ ldap_err2string(rc),
+ ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
+
+ if (ld_errno == LDAP_SERVER_DOWN) {
+ ldap_unbind(ldap_state->ldap_struct);
+ ldap_state->ldap_struct = NULL;
+ }
}
}
@@ -1289,7 +1302,7 @@ int smbldap_search_paged(struct smbldap_state *ldap_state,
/* construct cookie */
if (*cookie != NULL) {
ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
- ber_bvfree(*cookie); /* don't need it from last time */
+ ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
*cookie = NULL;
} else {
ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
@@ -1370,12 +1383,23 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
+ int ld_errno;
+
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
ldap_get_option(ldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(10,("Failed to modify dn: %s, error: %s "
- "(%s)\n", dn, ldap_err2string(rc),
- ld_error ? ld_error : "unknown"));
+ DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
+ "(%s)\n", dn, ld_errno,
+ ldap_err2string(rc),
+ ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
+
+ if (ld_errno == LDAP_SERVER_DOWN) {
+ ldap_unbind(ldap_state->ldap_struct);
+ ldap_state->ldap_struct = NULL;
+ }
}
}
@@ -1402,12 +1426,23 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
+ int ld_errno;
+
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
ldap_get_option(ldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(10,("Failed to add dn: %s, error: %s "
- "(%s)\n", dn, ldap_err2string(rc),
- ld_error ? ld_error : "unknown"));
+ DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
+ "(%s)\n", dn, ld_errno,
+ ldap_err2string(rc),
+ ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
+
+ if (ld_errno == LDAP_SERVER_DOWN) {
+ ldap_unbind(ldap_state->ldap_struct);
+ ldap_state->ldap_struct = NULL;
+ }
}
}
@@ -1434,12 +1469,23 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
+ int ld_errno;
+
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
ldap_get_option(ldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(10,("Failed to delete dn: %s, error: %s "
- "(%s)\n", dn, ldap_err2string(rc),
- ld_error ? ld_error : "unknown"));
+ DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
+ "(%s)\n", dn, ld_errno,
+ ldap_err2string(rc),
+ ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
+
+ if (ld_errno == LDAP_SERVER_DOWN) {
+ ldap_unbind(ldap_state->ldap_struct);
+ ldap_state->ldap_struct = NULL;
+ }
}
}
@@ -1465,12 +1511,23 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
clientctrls, retoidp, retdatap);
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
+ int ld_errno;
+
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_NUMBER, &ld_errno);
+
ldap_get_option(ldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(10,("Extended operation failed with error: %s "
- "(%s)\n", ldap_err2string(rc),
- ld_error ? ld_error : "unknown"));
+ DEBUG(10, ("Extended operation failed with error: "
+ "%d (%s) (%s)\n", ld_errno,
+ ldap_err2string(rc),
+ ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
+
+ if (ld_errno == LDAP_SERVER_DOWN) {
+ ldap_unbind(ldap_state->ldap_struct);
+ ldap_state->ldap_struct = NULL;
+ }
}
}
@@ -1703,3 +1760,24 @@ BOOL smbldap_has_naming_context(LDAP *ld, const char *naming_context)
const char *attrs[] = { "namingContexts", NULL };
return smbldap_check_root_dse(ld, attrs, naming_context);
}
+
+BOOL smbldap_set_creds(struct smbldap_state *ldap_state, BOOL anon, const char *dn, const char *secret)
+{
+ ldap_state->anonymous = anon;
+
+ /* free any previously set credential */
+
+ SAFE_FREE(ldap_state->bind_dn);
+ if (ldap_state->bind_secret) {
+ /* make sure secrets are zeroed out of memory */
+ memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
+ SAFE_FREE(ldap_state->bind_secret);
+ }
+
+ if ( ! anon) {
+ ldap_state->bind_dn = SMB_STRDUP(dn);
+ ldap_state->bind_secret = SMB_STRDUP(secret);
+ }
+
+ return True;
+}
diff --git a/source/lib/socket_wrapper.c b/source/lib/socket_wrapper.c
deleted file mode 100644
index e9c1404d113..00000000000
--- a/source/lib/socket_wrapper.c
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- Socket wrapper library. Passes all socket communication over
- unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
- is set.
- Copyright (C) Jelmer Vernooij 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"
-
-#ifdef _PUBLIC_
-#undef _PUBLIC_
-#endif
-#define _PUBLIC_
-
-#ifdef SOCKET_WRAPPER_REPLACE
-#undef accept
-#undef connect
-#undef bind
-#undef getpeername
-#undef getsockname
-#undef getsockopt
-#undef setsockopt
-#undef recvfrom
-#undef sendto
-#undef socket
-#undef close
-#endif
-
-/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
- * for now */
-#define REWRITE_CALLS
-
-#ifdef REWRITE_CALLS
-#define real_accept accept
-#define real_connect connect
-#define real_bind bind
-#define real_getpeername getpeername
-#define real_getsockname getsockname
-#define real_getsockopt getsockopt
-#define real_setsockopt setsockopt
-#define real_recvfrom recvfrom
-#define real_sendto sendto
-#define real_socket socket
-#define real_close close
-#endif
-
-#undef malloc
-#undef calloc
-#undef strdup
-/* we need to use a very terse format here as IRIX 6.4 silently
- truncates names to 16 chars, so if we use a longer name then we
- can't tell which port a packet came from with recvfrom()
-
- with this format we have 8 chars left for the directory name
-*/
-#define SOCKET_FORMAT "%c%02X%04X"
-#define SOCKET_TYPE_CHAR_TCP 'T'
-#define SOCKET_TYPE_CHAR_UDP 'U'
-
-static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
-{
- struct sockaddr *ret = (struct sockaddr *)malloc(len);
- memcpy(ret, data, len);
- return ret;
-}
-
-struct socket_info
-{
- int fd;
-
- int domain;
- int type;
- int protocol;
- int bound;
- int bcast;
-
- char *path;
- char *tmp_path;
-
- struct sockaddr *myname;
- socklen_t myname_len;
-
- struct sockaddr *peername;
- socklen_t peername_len;
-
- struct socket_info *prev, *next;
-};
-
-static struct socket_info *sockets = NULL;
-
-
-static const char *socket_wrapper_dir(void)
-{
- const char *s = getenv("SOCKET_WRAPPER_DIR");
- if (s == NULL) {
- return NULL;
- }
- if (strncmp(s, "./", 2) == 0) {
- s += 2;
- }
- return s;
-}
-
-static unsigned int socket_wrapper_default_iface(void)
-{
- const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
- if (s) {
- unsigned int iface;
- if (sscanf(s, "%u", &iface) == 1) {
- if (iface >= 1 && iface <= 0xFF) {
- return iface;
- }
- }
- }
-
- return 1;/* 127.0.0.1 */
-}
-
-static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
-{
- unsigned int iface;
- unsigned int prt;
- const char *p;
- char type;
-
- if ((*len) < sizeof(struct sockaddr_in)) {
- return 0;
- }
-
- p = strrchr(un->sun_path, '/');
- if (p) p++; else p = un->sun_path;
-
- if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
- errno = EINVAL;
- return -1;
- }
-
- if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
- errno = EINVAL;
- return -1;
- }
-
- if (iface == 0 || iface > 0xFF) {
- errno = EINVAL;
- return -1;
- }
-
- if (prt > 0xFFFF) {
- errno = EINVAL;
- return -1;
- }
-
- in->sin_family = AF_INET;
- in->sin_addr.s_addr = htonl((127<<24) | iface);
- in->sin_port = htons(prt);
-
- *len = sizeof(struct sockaddr_in);
- return 0;
-}
-
-static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
- int *bcast)
-{
- char u_type = '\0';
- char b_type = '\0';
- char a_type = '\0';
- char type = '\0';
- unsigned int addr= ntohl(in->sin_addr.s_addr);
- unsigned int prt = ntohs(in->sin_port);
- unsigned int iface;
- int is_bcast = 0;
-
- if (bcast) *bcast = 0;
-
- if (prt == 0) {
- errno = EINVAL;
- return -1;
- }
-
- switch (si->type) {
- case SOCK_STREAM:
- u_type = SOCKET_TYPE_CHAR_TCP;
- break;
- case SOCK_DGRAM:
- u_type = SOCKET_TYPE_CHAR_UDP;
- a_type = SOCKET_TYPE_CHAR_UDP;
- b_type = SOCKET_TYPE_CHAR_UDP;
- break;
- }
-
- if (a_type && addr == 0xFFFFFFFF) {
- /* 255.255.255.255 only udp */
- is_bcast = 2;
- type = a_type;
- iface = socket_wrapper_default_iface();
- } else if (b_type && addr == 0x7FFFFFFF) {
- /* 127.255.255.255 only udp */
- is_bcast = 1;
- type = b_type;
- iface = socket_wrapper_default_iface();
- } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
- /* 127.0.0.X */
- is_bcast = 0;
- type = u_type;
- iface = (addr & 0x000000FF);
- } else {
- errno = ENETUNREACH;
- return -1;
- }
-
- if (bcast) *bcast = is_bcast;
-
- if (is_bcast) {
- snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
- socket_wrapper_dir());
- /* the caller need to do more processing */
- return 0;
- }
-
- snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
- socket_wrapper_dir(), type, iface, prt);
-
- return 0;
-}
-
-static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
- int *bcast)
-{
- char u_type = '\0';
- char d_type = '\0';
- char b_type = '\0';
- char a_type = '\0';
- char type = '\0';
- unsigned int addr= ntohl(in->sin_addr.s_addr);
- unsigned int prt = ntohs(in->sin_port);
- unsigned int iface;
- struct stat st;
- int is_bcast = 0;
-
- if (bcast) *bcast = 0;
-
- switch (si->type) {
- case SOCK_STREAM:
- u_type = SOCKET_TYPE_CHAR_TCP;
- d_type = SOCKET_TYPE_CHAR_TCP;
- break;
- case SOCK_DGRAM:
- u_type = SOCKET_TYPE_CHAR_UDP;
- d_type = SOCKET_TYPE_CHAR_UDP;
- a_type = SOCKET_TYPE_CHAR_UDP;
- b_type = SOCKET_TYPE_CHAR_UDP;
- break;
- }
-
- if (addr == 0) {
- /* 0.0.0.0 */
- is_bcast = 0;
- type = d_type;
- iface = socket_wrapper_default_iface();
- } else if (a_type && addr == 0xFFFFFFFF) {
- /* 255.255.255.255 only udp */
- is_bcast = 2;
- type = a_type;
- iface = socket_wrapper_default_iface();
- } else if (b_type && addr == 0x7FFFFFFF) {
- /* 127.255.255.255 only udp */
- is_bcast = 1;
- type = b_type;
- iface = socket_wrapper_default_iface();
- } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
- /* 127.0.0.X */
- is_bcast = 0;
- type = u_type;
- iface = (addr & 0x000000FF);
- } else {
- errno = EADDRNOTAVAIL;
- return -1;
- }
-
- if (bcast) *bcast = is_bcast;
-
- if (prt == 0) {
- /* handle auto-allocation of ephemeral ports */
- for (prt = 5001; prt < 10000; prt++) {
- snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
- socket_wrapper_dir(), type, iface, prt);
- if (stat(un->sun_path, &st) == 0) continue;
-
- ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
- return 0;
- }
- errno = ENFILE;
- return -1;
- }
-
- snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
- socket_wrapper_dir(), type, iface, prt);
- return 0;
-}
-
-static struct socket_info *find_socket_info(int fd)
-{
- struct socket_info *i;
- for (i = sockets; i; i = i->next) {
- if (i->fd == fd)
- return i;
- }
-
- return NULL;
-}
-
-static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
- struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
-{
- if (!out_addr)
- return 0;
-
- out_addr->sun_family = AF_UNIX;
-
- switch (in_addr->sa_family) {
- case AF_INET:
- switch (si->type) {
- case SOCK_STREAM:
- case SOCK_DGRAM:
- break;
- default:
- errno = ESOCKTNOSUPPORT;
- return -1;
- }
- if (alloc_sock) {
- return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
- } else {
- return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
- }
- case AF_UNIX:
- memcpy(out_addr, in_addr, sizeof(*out_addr));
- return 0;
- default:
- break;
- }
-
- errno = EAFNOSUPPORT;
- return -1;
-}
-
-static int sockaddr_convert_from_un(const struct socket_info *si,
- const struct sockaddr_un *in_addr,
- socklen_t un_addrlen,
- int family,
- struct sockaddr *out_addr,
- socklen_t *_out_addrlen)
-{
- socklen_t out_addrlen;
-
- if (out_addr == NULL || _out_addrlen == NULL)
- return 0;
-
- if (un_addrlen == 0) {
- *_out_addrlen = 0;
- return 0;
- }
-
- out_addrlen = *_out_addrlen;
- if (out_addrlen > un_addrlen) {
- out_addrlen = un_addrlen;
- }
-
- switch (family) {
- case AF_INET:
- switch (si->type) {
- case SOCK_STREAM:
- case SOCK_DGRAM:
- break;
- default:
- errno = ESOCKTNOSUPPORT;
- return -1;
- }
- return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
- case AF_UNIX:
- memcpy(out_addr, in_addr, out_addrlen);
- *_out_addrlen = out_addrlen;
- return 0;
- default:
- break;
- }
-
- errno = EAFNOSUPPORT;
- return -1;
-}
-
-_PUBLIC_ int swrap_socket(int domain, int type, int protocol)
-{
- struct socket_info *si;
- int fd;
-
- if (!socket_wrapper_dir()) {
- return real_socket(domain, type, protocol);
- }
-
- fd = real_socket(AF_UNIX, type, 0);
-
- if (fd == -1) return -1;
-
- si = calloc(1, sizeof(struct socket_info));
-
- si->domain = domain;
- si->type = type;
- si->protocol = protocol;
- si->fd = fd;
-
- DLIST_ADD(sockets, si);
-
- return si->fd;
-}
-
-_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- struct socket_info *parent_si, *child_si;
- int fd;
- struct sockaddr_un un_addr;
- socklen_t un_addrlen = sizeof(un_addr);
- struct sockaddr_un un_my_addr;
- socklen_t un_my_addrlen = sizeof(un_my_addr);
- struct sockaddr my_addr;
- socklen_t my_addrlen = sizeof(my_addr);
- int ret;
-
- parent_si = find_socket_info(s);
- if (!parent_si) {
- return real_accept(s, addr, addrlen);
- }
-
- memset(&un_addr, 0, sizeof(un_addr));
- memset(&un_my_addr, 0, sizeof(un_my_addr));
- memset(&my_addr, 0, sizeof(my_addr));
-
- ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
- if (ret == -1) return ret;
-
- fd = ret;
-
- ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
- parent_si->domain, addr, addrlen);
- if (ret == -1) return ret;
-
- child_si = malloc(sizeof(struct socket_info));
- memset(child_si, 0, sizeof(*child_si));
-
- child_si->fd = fd;
- child_si->domain = parent_si->domain;
- child_si->type = parent_si->type;
- child_si->protocol = parent_si->protocol;
- child_si->bound = 1;
-
- ret = real_getsockname(fd, &un_my_addr, &un_my_addrlen);
- if (ret == -1) return ret;
-
- ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
- child_si->domain, &my_addr, &my_addrlen);
- if (ret == -1) return ret;
-
- child_si->myname_len = my_addrlen;
- child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
-
- child_si->peername_len = *addrlen;
- child_si->peername = sockaddr_dup(addr, *addrlen);
-
- DLIST_ADD(sockets, child_si);
-
- return fd;
-}
-
-/* using sendto() or connect() on an unbound socket would give the
- recipient no way to reply, as unlike UDP and TCP, a unix domain
- socket can't auto-assign emphemeral port numbers, so we need to
- assign it here */
-static int swrap_auto_bind(struct socket_info *si)
-{
- struct sockaddr_un un_addr;
- struct sockaddr_in in;
- int i;
- char type;
- int ret;
- struct stat st;
-
- un_addr.sun_family = AF_UNIX;
-
- switch (si->type) {
- case SOCK_STREAM:
- type = SOCKET_TYPE_CHAR_TCP;
- break;
- case SOCK_DGRAM:
- type = SOCKET_TYPE_CHAR_UDP;
- break;
- default:
- errno = ESOCKTNOSUPPORT;
- return -1;
- }
-
- for (i=0;i<1000;i++) {
- snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
- "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
- type, socket_wrapper_default_iface(), i + 10000);
- if (stat(un_addr.sun_path, &st) == 0) continue;
-
- ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
- if (ret == -1) return ret;
-
- si->tmp_path = strdup(un_addr.sun_path);
- si->bound = 1;
- break;
- }
- if (i == 1000) {
- errno = ENFILE;
- return -1;
- }
-
- memset(&in, 0, sizeof(in));
- in.sin_family = AF_INET;
- in.sin_port = htons(i);
- in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
-
- si->myname_len = sizeof(in);
- si->myname = sockaddr_dup(&in, si->myname_len);
- si->bound = 1;
- return 0;
-}
-
-
-_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
-{
- int ret;
- struct sockaddr_un un_addr;
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_connect(s, serv_addr, addrlen);
- }
-
- if (si->bound == 0 && si->domain != AF_UNIX) {
- ret = swrap_auto_bind(si);
- if (ret == -1) return -1;
- }
-
- ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
- if (ret == -1) return -1;
-
- ret = real_connect(s, (struct sockaddr *)&un_addr,
- sizeof(struct sockaddr_un));
-
- /* to give better errors */
- if (serv_addr->sa_family == AF_INET) {
- if (ret == -1 && errno == ENOENT) {
- errno = EHOSTUNREACH;
- }
- }
-
- if (ret == 0) {
- si->peername_len = addrlen;
- si->peername = sockaddr_dup(serv_addr, addrlen);
- }
-
- return ret;
-}
-
-_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
-{
- int ret;
- struct sockaddr_un un_addr;
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_bind(s, myaddr, addrlen);
- }
-
- si->myname_len = addrlen;
- si->myname = sockaddr_dup(myaddr, addrlen);
-
- ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
- if (ret == -1) return -1;
-
- unlink(un_addr.sun_path);
-
- ret = real_bind(s, (struct sockaddr *)&un_addr,
- sizeof(struct sockaddr_un));
-
- if (ret == 0) {
- si->bound = 1;
- }
-
- return ret;
-}
-
-_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
-{
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_getpeername(s, name, addrlen);
- }
-
- if (!si->peername)
- {
- errno = ENOTCONN;
- return -1;
- }
-
- memcpy(name, si->peername, si->peername_len);
- *addrlen = si->peername_len;
-
- return 0;
-}
-
-_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
-{
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_getsockname(s, name, addrlen);
- }
-
- memcpy(name, si->myname, si->myname_len);
- *addrlen = si->myname_len;
-
- return 0;
-}
-
-_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
-{
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_getsockopt(s, level, optname, optval, optlen);
- }
-
- if (level == SOL_SOCKET) {
- return real_getsockopt(s, level, optname, optval, optlen);
- }
-
- switch (si->domain) {
- case AF_UNIX:
- return real_getsockopt(s, level, optname, optval, optlen);
- default:
- errno = ENOPROTOOPT;
- return -1;
- }
-}
-
-_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
-{
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_setsockopt(s, level, optname, optval, optlen);
- }
-
- if (level == SOL_SOCKET) {
- return real_setsockopt(s, level, optname, optval, optlen);
- }
-
- switch (si->domain) {
- case AF_UNIX:
- return real_setsockopt(s, level, optname, optval, optlen);
- case AF_INET:
- /* Silence some warnings */
-#ifdef TCP_NODELAY
- if (optname == TCP_NODELAY)
- return 0;
-#endif
- default:
- errno = ENOPROTOOPT;
- return -1;
- }
-}
-
-_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
-{
- struct sockaddr_un un_addr;
- socklen_t un_addrlen = sizeof(un_addr);
- int ret;
- struct socket_info *si = find_socket_info(s);
-
- if (!si) {
- return real_recvfrom(s, buf, len, flags, from, fromlen);
- }
-
- /* irix 6.4 forgets to null terminate the sun_path string :-( */
- memset(&un_addr, 0, sizeof(un_addr));
- ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
- if (ret == -1)
- return ret;
-
- if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
- si->domain, from, fromlen) == -1) {
- return -1;
- }
-
- return ret;
-}
-
-
-_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
-{
- struct sockaddr_un un_addr;
- int ret;
- struct socket_info *si = find_socket_info(s);
- int bcast = 0;
-
- if (!si) {
- return real_sendto(s, buf, len, flags, to, tolen);
- }
-
- if (si->bound == 0 && si->domain != AF_UNIX) {
- ret = swrap_auto_bind(si);
- if (ret == -1) return -1;
- }
-
- ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
- if (ret == -1) return -1;
-
- if (bcast) {
- struct stat st;
- unsigned int iface;
- unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
- char type;
-
- type = SOCKET_TYPE_CHAR_UDP;
-
- for(iface=0; iface <= 0xFF; iface++) {
- snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
- socket_wrapper_dir(), type, iface, prt);
- if (stat(un_addr.sun_path, &st) != 0) continue;
-
- /* ignore the any errors in broadcast sends */
- real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
- }
- return len;
- }
-
- ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
-
- /* to give better errors */
- if (to->sa_family == AF_INET) {
- if (ret == -1 && errno == ENOENT) {
- errno = EHOSTUNREACH;
- }
- }
-
- return ret;
-}
-
-_PUBLIC_ int swrap_close(int fd)
-{
- struct socket_info *si = find_socket_info(fd);
-
- if (si) {
- DLIST_REMOVE(sockets, si);
-
- free(si->path);
- free(si->myname);
- free(si->peername);
- if (si->tmp_path) {
- unlink(si->tmp_path);
- free(si->tmp_path);
- }
- free(si);
- }
-
- return real_close(fd);
-}
diff --git a/source/lib/socket_wrapper/config.m4 b/source/lib/socket_wrapper/config.m4
new file mode 100644
index 00000000000..42212abc7fc
--- /dev/null
+++ b/source/lib/socket_wrapper/config.m4
@@ -0,0 +1,22 @@
+AC_ARG_ENABLE(socket-wrapper,
+[ --enable-socket-wrapper Turn on socket wrapper library (default=no)])
+
+DEFAULT_TEST_TARGET=test-noswrap
+HAVE_SOCKET_WRAPPER=no
+
+if eval "test x$developer = xyes"; then
+ enable_socket_wrapper=yes
+fi
+
+if eval "test x$enable_socket_wrapper = xyes"; then
+ AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library])
+ DEFAULT_TEST_TARGET=test-swrap
+ HAVE_SOCKET_WRAPPER=yes
+
+ # this is only used for samba3
+ SOCKET_WRAPPER_OBJS="lib/socket_wrapper/socket_wrapper.o"
+fi
+
+AC_SUBST(DEFAULT_TEST_TARGET)
+AC_SUBST(HAVE_SOCKET_WRAPPER)
+AC_SUBST(SOCKET_WRAPPER_OBJS)
diff --git a/source/lib/socket_wrapper/socket_wrapper.c b/source/lib/socket_wrapper/socket_wrapper.c
new file mode 100644
index 00000000000..3a72c5a74a0
--- /dev/null
+++ b/source/lib/socket_wrapper/socket_wrapper.c
@@ -0,0 +1,1596 @@
+/*
+ * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
+ * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ Socket wrapper library. Passes all socket communication over
+ unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
+ is set.
+*/
+
+#ifdef _SAMBA_BUILD_
+
+#define SOCKET_WRAPPER_NOT_REPLACE
+#include "includes.h"
+#include "system/network.h"
+#include "system/filesys.h"
+
+#ifdef malloc
+#undef malloc
+#endif
+#ifdef calloc
+#undef calloc
+#endif
+#ifdef strdup
+#undef strdup
+#endif
+
+#else /* _SAMBA_BUILD_ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#define _PUBLIC_
+
+#endif
+
+#define SWRAP_DLIST_ADD(list,item) do { \
+ if (!(list)) { \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+ (list) = (item); \
+ } else { \
+ (item)->prev = NULL; \
+ (item)->next = (list); \
+ (list)->prev = (item); \
+ (list) = (item); \
+ } \
+} while (0)
+
+#define SWRAP_DLIST_REMOVE(list,item) do { \
+ if ((list) == (item)) { \
+ (list) = (item)->next; \
+ if (list) { \
+ (list)->prev = NULL; \
+ } \
+ } else { \
+ if ((item)->prev) { \
+ (item)->prev->next = (item)->next; \
+ } \
+ if ((item)->next) { \
+ (item)->next->prev = (item)->prev; \
+ } \
+ } \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+} while (0)
+
+/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
+ * for now */
+#define REWRITE_CALLS
+
+#ifdef REWRITE_CALLS
+#define real_accept accept
+#define real_connect connect
+#define real_bind bind
+#define real_listen listen
+#define real_getpeername getpeername
+#define real_getsockname getsockname
+#define real_getsockopt getsockopt
+#define real_setsockopt setsockopt
+#define real_recvfrom recvfrom
+#define real_sendto sendto
+#define real_ioctl ioctl
+#define real_recv recv
+#define real_send send
+#define real_socket socket
+#define real_close close
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY_TZ
+#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
+#else
+#define swrapGetTimeOfDay(tval) gettimeofday(tval)
+#endif
+
+/* we need to use a very terse format here as IRIX 6.4 silently
+ truncates names to 16 chars, so if we use a longer name then we
+ can't tell which port a packet came from with recvfrom()
+
+ with this format we have 8 chars left for the directory name
+*/
+#define SOCKET_FORMAT "%c%02X%04X"
+#define SOCKET_TYPE_CHAR_TCP 'T'
+#define SOCKET_TYPE_CHAR_UDP 'U'
+
+#define MAX_WRAPPED_INTERFACES 16
+
+static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
+{
+ struct sockaddr *ret = (struct sockaddr *)malloc(len);
+ memcpy(ret, data, len);
+ return ret;
+}
+
+struct socket_info
+{
+ int fd;
+
+ int family;
+ int type;
+ int protocol;
+ int bound;
+ int bcast;
+ int is_server;
+
+ char *path;
+ char *tmp_path;
+
+ struct sockaddr *myname;
+ socklen_t myname_len;
+
+ struct sockaddr *peername;
+ socklen_t peername_len;
+
+ struct {
+ unsigned long pck_snd;
+ unsigned long pck_rcv;
+ } io;
+
+ struct socket_info *prev, *next;
+};
+
+static struct socket_info *sockets;
+
+
+static const char *socket_wrapper_dir(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DIR");
+ if (s == NULL) {
+ return NULL;
+ }
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+ return s;
+}
+
+static unsigned int socket_wrapper_default_iface(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
+ if (s) {
+ unsigned int iface;
+ if (sscanf(s, "%u", &iface) == 1) {
+ if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
+ return iface;
+ }
+ }
+ }
+
+ return 1;/* 127.0.0.1 */
+}
+
+static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
+{
+ unsigned int iface;
+ unsigned int prt;
+ const char *p;
+ char type;
+
+ if ((*len) < sizeof(struct sockaddr_in)) {
+ return 0;
+ }
+
+ p = strrchr(un->sun_path, '/');
+ if (p) p++; else p = un->sun_path;
+
+ if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (prt > 0xFFFF) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ in->sin_family = AF_INET;
+ in->sin_addr.s_addr = htonl((127<<24) | iface);
+ in->sin_port = htons(prt);
+
+ *len = sizeof(struct sockaddr_in);
+ return 0;
+}
+
+static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
+ int *bcast)
+{
+ char u_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+ char type = '\0';
+ unsigned int addr= ntohl(in->sin_addr.s_addr);
+ unsigned int prt = ntohs(in->sin_port);
+ unsigned int iface;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ if (prt == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP;
+ a_type = SOCKET_TYPE_CHAR_UDP;
+ b_type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ }
+
+ if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ iface = socket_wrapper_default_iface();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ iface = socket_wrapper_default_iface();
+ } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
+ /* 127.0.0.X */
+ is_bcast = 0;
+ type = u_type;
+ iface = (addr & 0x000000FF);
+ } else {
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+ if (bcast) *bcast = is_bcast;
+
+ if (is_bcast) {
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
+ socket_wrapper_dir());
+ /* the caller need to do more processing */
+ return 0;
+ }
+
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+
+ return 0;
+}
+
+static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
+ int *bcast)
+{
+ char u_type = '\0';
+ char d_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+ char type = '\0';
+ unsigned int addr= ntohl(in->sin_addr.s_addr);
+ unsigned int prt = ntohs(in->sin_port);
+ unsigned int iface;
+ struct stat st;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP;
+ d_type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP;
+ d_type = SOCKET_TYPE_CHAR_UDP;
+ a_type = SOCKET_TYPE_CHAR_UDP;
+ b_type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ }
+
+ if (addr == 0) {
+ /* 0.0.0.0 */
+ is_bcast = 0;
+ type = d_type;
+ iface = socket_wrapper_default_iface();
+ } else if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ iface = socket_wrapper_default_iface();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ iface = socket_wrapper_default_iface();
+ } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
+ /* 127.0.0.X */
+ is_bcast = 0;
+ type = u_type;
+ iface = (addr & 0x000000FF);
+ } else {
+ errno = EADDRNOTAVAIL;
+ return -1;
+ }
+
+ if (bcast) *bcast = is_bcast;
+
+ if (prt == 0) {
+ /* handle auto-allocation of ephemeral ports */
+ for (prt = 5001; prt < 10000; prt++) {
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un->sun_path, &st) == 0) continue;
+
+ ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
+ return 0;
+ }
+ errno = ENFILE;
+ return -1;
+ }
+
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ return 0;
+}
+
+static struct socket_info *find_socket_info(int fd)
+{
+ struct socket_info *i;
+ for (i = sockets; i; i = i->next) {
+ if (i->fd == fd)
+ return i;
+ }
+
+ return NULL;
+}
+
+static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
+ struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
+{
+ if (!out_addr)
+ return 0;
+
+ out_addr->sun_family = AF_UNIX;
+
+ switch (in_addr->sa_family) {
+ case AF_INET:
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ if (alloc_sock) {
+ return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
+ } else {
+ return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
+ }
+ default:
+ break;
+ }
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+static int sockaddr_convert_from_un(const struct socket_info *si,
+ const struct sockaddr_un *in_addr,
+ socklen_t un_addrlen,
+ int family,
+ struct sockaddr *out_addr,
+ socklen_t *_out_addrlen)
+{
+ socklen_t out_addrlen;
+
+ if (out_addr == NULL || _out_addrlen == NULL)
+ return 0;
+
+ if (un_addrlen == 0) {
+ *_out_addrlen = 0;
+ return 0;
+ }
+
+ out_addrlen = *_out_addrlen;
+ if (out_addrlen > un_addrlen) {
+ out_addrlen = un_addrlen;
+ }
+
+ switch (family) {
+ case AF_INET:
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
+ default:
+ break;
+ }
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+enum swrap_packet_type {
+ SWRAP_CONNECT_SEND,
+ SWRAP_CONNECT_UNREACH,
+ SWRAP_CONNECT_RECV,
+ SWRAP_CONNECT_ACK,
+ SWRAP_ACCEPT_SEND,
+ SWRAP_ACCEPT_RECV,
+ SWRAP_ACCEPT_ACK,
+ SWRAP_RECVFROM,
+ SWRAP_SENDTO,
+ SWRAP_SENDTO_UNREACH,
+ SWRAP_PENDING_RST,
+ SWRAP_RECV,
+ SWRAP_RECV_RST,
+ SWRAP_SEND,
+ SWRAP_SEND_RST,
+ SWRAP_CLOSE_SEND,
+ SWRAP_CLOSE_RECV,
+ SWRAP_CLOSE_ACK
+};
+
+struct swrap_file_hdr {
+ unsigned long magic;
+ unsigned short version_major;
+ unsigned short version_minor;
+ long timezone;
+ unsigned long sigfigs;
+ unsigned long frame_max_len;
+#define SWRAP_FRAME_LENGTH_MAX 0xFFFF
+ unsigned long link_type;
+};
+#define SWRAP_FILE_HDR_SIZE 24
+
+struct swrap_packet {
+ struct {
+ unsigned long seconds;
+ unsigned long micro_seconds;
+ unsigned long recorded_length;
+ unsigned long full_length;
+ } frame;
+#define SWRAP_PACKET__FRAME_SIZE 16
+
+ struct {
+ struct {
+ unsigned char ver_hdrlen;
+ unsigned char tos;
+ unsigned short packet_length;
+ unsigned short identification;
+ unsigned char flags;
+ unsigned char fragment;
+ unsigned char ttl;
+ unsigned char protocol;
+ unsigned short hdr_checksum;
+ unsigned long src_addr;
+ unsigned long dest_addr;
+ } hdr;
+#define SWRAP_PACKET__IP_HDR_SIZE 20
+
+ union {
+ struct {
+ unsigned short source_port;
+ unsigned short dest_port;
+ unsigned long seq_num;
+ unsigned long ack_num;
+ unsigned char hdr_length;
+ unsigned char control;
+ unsigned short window;
+ unsigned short checksum;
+ unsigned short urg;
+ } tcp;
+#define SWRAP_PACKET__IP_P_TCP_SIZE 20
+ struct {
+ unsigned short source_port;
+ unsigned short dest_port;
+ unsigned short length;
+ unsigned short checksum;
+ } udp;
+#define SWRAP_PACKET__IP_P_UDP_SIZE 8
+ struct {
+ unsigned char type;
+ unsigned char code;
+ unsigned short checksum;
+ unsigned long unused;
+ } icmp;
+#define SWRAP_PACKET__IP_P_ICMP_SIZE 8
+ } p;
+ } ip;
+};
+#define SWRAP_PACKET_SIZE 56
+
+static const char *socket_wrapper_pcap_file(void)
+{
+ static int initialized = 0;
+ static const char *s = NULL;
+ static const struct swrap_file_hdr h;
+ static const struct swrap_packet p;
+
+ if (initialized == 1) {
+ return s;
+ }
+ initialized = 1;
+
+ /*
+ * TODO: don't use the structs use plain buffer offsets
+ * and PUSH_U8(), PUSH_U16() and PUSH_U32()
+ *
+ * for now make sure we disable PCAP support
+ * if the struct has alignment!
+ */
+ if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p) != SWRAP_PACKET_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
+ return NULL;
+ }
+
+ s = getenv("SOCKET_WRAPPER_PCAP_FILE");
+ if (s == NULL) {
+ return NULL;
+ }
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+ return s;
+}
+
+static struct swrap_packet *swrap_packet_init(struct timeval *tval,
+ const struct sockaddr_in *src_addr,
+ const struct sockaddr_in *dest_addr,
+ int socket_type,
+ const unsigned char *payload,
+ size_t payload_len,
+ unsigned long tcp_seq,
+ unsigned long tcp_ack,
+ unsigned char tcp_ctl,
+ int unreachable,
+ size_t *_packet_len)
+{
+ struct swrap_packet *ret;
+ struct swrap_packet *packet;
+ size_t packet_len;
+ size_t alloc_len;
+ size_t nonwire_len = sizeof(packet->frame);
+ size_t wire_hdr_len = 0;
+ size_t wire_len = 0;
+ size_t icmp_hdr_len = 0;
+ size_t icmp_truncate_len = 0;
+ unsigned char protocol = 0, icmp_protocol = 0;
+ unsigned short src_port = src_addr->sin_port;
+ unsigned short dest_port = dest_addr->sin_port;
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ protocol = 0x06; /* TCP */
+ wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+
+ case SOCK_DGRAM:
+ protocol = 0x11; /* UDP */
+ wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+ }
+
+ if (unreachable) {
+ icmp_protocol = protocol;
+ protocol = 0x01; /* ICMP */
+ if (wire_len > 64 ) {
+ icmp_truncate_len = wire_len - 64;
+ }
+ icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
+ wire_hdr_len += icmp_hdr_len;
+ wire_len += icmp_hdr_len;
+ }
+
+ packet_len = nonwire_len + wire_len;
+ alloc_len = packet_len;
+ if (alloc_len < sizeof(struct swrap_packet)) {
+ alloc_len = sizeof(struct swrap_packet);
+ }
+ ret = (struct swrap_packet *)malloc(alloc_len);
+ if (!ret) return NULL;
+
+ packet = ret;
+
+ packet->frame.seconds = tval->tv_sec;
+ packet->frame.micro_seconds = tval->tv_usec;
+ packet->frame.recorded_length = wire_len - icmp_truncate_len;
+ packet->frame.full_length = wire_len - icmp_truncate_len;
+
+ packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ packet->ip.hdr.tos = 0x00;
+ packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
+ packet->ip.hdr.identification = htons(0xFFFF);
+ packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
+ packet->ip.hdr.fragment = htons(0x0000);
+ packet->ip.hdr.ttl = 0xFF;
+ packet->ip.hdr.protocol = protocol;
+ packet->ip.hdr.hdr_checksum = htons(0x0000);
+ packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
+ packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
+
+ if (unreachable) {
+ packet->ip.p.icmp.type = 0x03; /* destination unreachable */
+ packet->ip.p.icmp.code = 0x01; /* host unreachable */
+ packet->ip.p.icmp.checksum = htons(0x0000);
+ packet->ip.p.icmp.unused = htonl(0x00000000);
+
+ /* set the ip header in the ICMP payload */
+ packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
+ packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ packet->ip.hdr.tos = 0x00;
+ packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
+ packet->ip.hdr.identification = htons(0xFFFF);
+ packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
+ packet->ip.hdr.fragment = htons(0x0000);
+ packet->ip.hdr.ttl = 0xFF;
+ packet->ip.hdr.protocol = icmp_protocol;
+ packet->ip.hdr.hdr_checksum = htons(0x0000);
+ packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
+ packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
+
+ src_port = dest_addr->sin_port;
+ dest_port = src_addr->sin_port;
+ }
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ packet->ip.p.tcp.source_port = src_port;
+ packet->ip.p.tcp.dest_port = dest_port;
+ packet->ip.p.tcp.seq_num = htonl(tcp_seq);
+ packet->ip.p.tcp.ack_num = htonl(tcp_ack);
+ packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
+ packet->ip.p.tcp.control = tcp_ctl;
+ packet->ip.p.tcp.window = htons(0x7FFF);
+ packet->ip.p.tcp.checksum = htons(0x0000);
+ packet->ip.p.tcp.urg = htons(0x0000);
+
+ break;
+
+ case SOCK_DGRAM:
+ packet->ip.p.udp.source_port = src_addr->sin_port;
+ packet->ip.p.udp.dest_port = dest_addr->sin_port;
+ packet->ip.p.udp.length = htons(8 + payload_len);
+ packet->ip.p.udp.checksum = htons(0x0000);
+
+ break;
+ }
+
+ if (payload && payload_len > 0) {
+ unsigned char *p = (unsigned char *)ret;
+ p += nonwire_len;
+ p += wire_hdr_len;
+ memcpy(p, payload, payload_len);
+ }
+
+ *_packet_len = packet_len - icmp_truncate_len;
+ return ret;
+}
+
+static int swrap_get_pcap_fd(const char *fname)
+{
+ static int fd = -1;
+
+ if (fd != -1) return fd;
+
+ fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
+ if (fd != -1) {
+ struct swrap_file_hdr file_hdr;
+ file_hdr.magic = 0xA1B2C3D4;
+ file_hdr.version_major = 0x0002;
+ file_hdr.version_minor = 0x0004;
+ file_hdr.timezone = 0x00000000;
+ file_hdr.sigfigs = 0x00000000;
+ file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
+ file_hdr.link_type = 0x0065; /* 101 RAW IP */
+
+ write(fd, &file_hdr, sizeof(file_hdr));
+ return fd;
+ }
+
+ fd = open(fname, O_WRONLY|O_APPEND, 0644);
+
+ return fd;
+}
+
+static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
+ enum swrap_packet_type type,
+ const void *buf, size_t len)
+{
+ const struct sockaddr_in *src_addr;
+ const struct sockaddr_in *dest_addr;
+ const char *file_name;
+ unsigned long tcp_seq = 0;
+ unsigned long tcp_ack = 0;
+ unsigned char tcp_ctl = 0;
+ int unreachable = 0;
+ struct timeval tv;
+ struct swrap_packet *packet;
+ size_t packet_len = 0;
+ int fd;
+
+ file_name = socket_wrapper_pcap_file();
+ if (!file_name) {
+ return;
+ }
+
+ if (si->family != AF_INET) {
+ return;
+ }
+
+ switch (type) {
+ case SWRAP_CONNECT_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CONNECT_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x12; /** SYN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CONNECT_UNREACH:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
+ tcp_seq = si->io.pck_snd - 1;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_CONNECT_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_ACCEPT_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x12; /* SYN,ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_SEND:
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SEND_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ swrap_dump_packet(si, si->peername,
+ SWRAP_SENDTO_UNREACH,
+ buf, len);
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /** RST,ACK */
+
+ break;
+
+ case SWRAP_PENDING_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_RECV:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_RECV_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_SENDTO:
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SENDTO_UNREACH:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_RECVFROM:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_CLOSE_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x11; /* FIN, ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CLOSE_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x11; /* FIN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CLOSE_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+ default:
+ return;
+ }
+
+ swrapGetTimeOfDay(&tv);
+
+ packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
+ (const unsigned char *)buf, len,
+ tcp_seq, tcp_ack, tcp_ctl, unreachable,
+ &packet_len);
+ if (!packet) {
+ return;
+ }
+
+ fd = swrap_get_pcap_fd(file_name);
+ if (fd != -1) {
+ write(fd, packet, packet_len);
+ }
+
+ free(packet);
+}
+
+_PUBLIC_ int swrap_socket(int family, int type, int protocol)
+{
+ struct socket_info *si;
+ int fd;
+
+ if (!socket_wrapper_dir()) {
+ return real_socket(family, type, protocol);
+ }
+
+ switch (family) {
+ case AF_INET:
+ break;
+ case AF_UNIX:
+ return real_socket(family, type, protocol);
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ switch (type) {
+ case SOCK_STREAM:
+ break;
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ switch (protocol) {
+ case 0:
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ fd = real_socket(AF_UNIX, type, 0);
+
+ if (fd == -1) return -1;
+
+ si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+
+ si->family = family;
+ si->type = type;
+ si->protocol = protocol;
+ si->fd = fd;
+
+ SWRAP_DLIST_ADD(sockets, si);
+
+ return si->fd;
+}
+
+_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct socket_info *parent_si, *child_si;
+ int fd;
+ struct sockaddr_un un_addr;
+ socklen_t un_addrlen = sizeof(un_addr);
+ struct sockaddr_un un_my_addr;
+ socklen_t un_my_addrlen = sizeof(un_my_addr);
+ struct sockaddr my_addr;
+ socklen_t my_addrlen = sizeof(my_addr);
+ int ret;
+
+ parent_si = find_socket_info(s);
+ if (!parent_si) {
+ return real_accept(s, addr, addrlen);
+ }
+
+ memset(&un_addr, 0, sizeof(un_addr));
+ memset(&un_my_addr, 0, sizeof(un_my_addr));
+ memset(&my_addr, 0, sizeof(my_addr));
+
+ ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
+ if (ret == -1) return ret;
+
+ fd = ret;
+
+ ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
+ parent_si->family, addr, addrlen);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+
+ child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
+ memset(child_si, 0, sizeof(*child_si));
+
+ child_si->fd = fd;
+ child_si->family = parent_si->family;
+ child_si->type = parent_si->type;
+ child_si->protocol = parent_si->protocol;
+ child_si->bound = 1;
+ child_si->is_server = 1;
+
+ ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
+ if (ret == -1) {
+ free(child_si);
+ close(fd);
+ return ret;
+ }
+
+ ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
+ child_si->family, &my_addr, &my_addrlen);
+ if (ret == -1) {
+ free(child_si);
+ close(fd);
+ return ret;
+ }
+
+ child_si->myname_len = my_addrlen;
+ child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
+
+ child_si->peername_len = *addrlen;
+ child_si->peername = sockaddr_dup(addr, *addrlen);
+
+ SWRAP_DLIST_ADD(sockets, child_si);
+
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
+
+ return fd;
+}
+
+static int autobind_start_init;
+static int autobind_start;
+
+/* using sendto() or connect() on an unbound socket would give the
+ recipient no way to reply, as unlike UDP and TCP, a unix domain
+ socket can't auto-assign emphemeral port numbers, so we need to
+ assign it here */
+static int swrap_auto_bind(struct socket_info *si)
+{
+ struct sockaddr_un un_addr;
+ struct sockaddr_in in;
+ int i;
+ char type;
+ int ret;
+ int port;
+ struct stat st;
+
+ if (autobind_start_init != 1) {
+ autobind_start_init = 1;
+ autobind_start = getpid();
+ autobind_start %= 50000;
+ autobind_start += 10000;
+ }
+
+ un_addr.sun_family = AF_UNIX;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ if (autobind_start > 60000) {
+ autobind_start = 10000;
+ }
+
+ for (i=0;i<1000;i++) {
+ port = autobind_start + i;
+ snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
+ "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
+ type, socket_wrapper_default_iface(), port);
+ if (stat(un_addr.sun_path, &st) == 0) continue;
+
+ ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
+ if (ret == -1) return ret;
+
+ si->tmp_path = strdup(un_addr.sun_path);
+ si->bound = 1;
+ autobind_start = port + 1;
+ break;
+ }
+ if (i == 1000) {
+ errno = ENFILE;
+ return -1;
+ }
+
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ in.sin_port = htons(port);
+ in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
+
+ si->myname_len = sizeof(in);
+ si->myname = sockaddr_dup(&in, si->myname_len);
+ return 0;
+}
+
+
+_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+ int ret;
+ struct sockaddr_un un_addr;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_connect(s, serv_addr, addrlen);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(si);
+ if (ret == -1) return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
+ if (ret == -1) return -1;
+
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
+
+ ret = real_connect(s, (struct sockaddr *)&un_addr,
+ sizeof(struct sockaddr_un));
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == 0) {
+ si->peername_len = addrlen;
+ si->peername = sockaddr_dup(serv_addr, addrlen);
+
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
+ } else {
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
+{
+ int ret;
+ struct sockaddr_un un_addr;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_bind(s, myaddr, addrlen);
+ }
+
+ si->myname_len = addrlen;
+ si->myname = sockaddr_dup(myaddr, addrlen);
+
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
+ if (ret == -1) return -1;
+
+ unlink(un_addr.sun_path);
+
+ ret = real_bind(s, (struct sockaddr *)&un_addr,
+ sizeof(struct sockaddr_un));
+
+ if (ret == 0) {
+ si->bound = 1;
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_listen(int s, int backlog)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_listen(s, backlog);
+ }
+
+ ret = real_listen(s, backlog);
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getpeername(s, name, addrlen);
+ }
+
+ if (!si->peername)
+ {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ memcpy(name, si->peername, si->peername_len);
+ *addrlen = si->peername_len;
+
+ return 0;
+}
+
+_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getsockname(s, name, addrlen);
+ }
+
+ memcpy(name, si->myname, si->myname_len);
+ *addrlen = si->myname_len;
+
+ return 0;
+}
+
+_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getsockopt(s, level, optname, optval, optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ return real_getsockopt(s, level, optname, optval, optlen);
+ }
+
+ errno = ENOPROTOOPT;
+ return -1;
+}
+
+_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_setsockopt(s, level, optname, optval, optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ return real_setsockopt(s, level, optname, optval, optlen);
+ }
+
+ switch (si->family) {
+ case AF_INET:
+ return 0;
+ default:
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+}
+
+_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
+{
+ struct sockaddr_un un_addr;
+ socklen_t un_addrlen = sizeof(un_addr);
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_recvfrom(s, buf, len, flags, from, fromlen);
+ }
+
+ /* irix 6.4 forgets to null terminate the sun_path string :-( */
+ memset(&un_addr, 0, sizeof(un_addr));
+ ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
+ if (ret == -1)
+ return ret;
+
+ if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
+ si->family, from, fromlen) == -1) {
+ return -1;
+ }
+
+ swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
+
+ return ret;
+}
+
+
+_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
+{
+ struct sockaddr_un un_addr;
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+ int bcast = 0;
+
+ if (!si) {
+ return real_sendto(s, buf, len, flags, to, tolen);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(si);
+ if (ret == -1) return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
+ if (ret == -1) return -1;
+
+ if (bcast) {
+ struct stat st;
+ unsigned int iface;
+ unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
+ char type;
+
+ type = SOCKET_TYPE_CHAR_UDP;
+
+ for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
+ snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un_addr.sun_path, &st) != 0) continue;
+
+ /* ignore the any errors in broadcast sends */
+ real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
+ }
+
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+
+ return len;
+ }
+
+ ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == -1) {
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+ swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
+ } else {
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_ioctl(int s, int r, void *p)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+ int value;
+
+ if (!si) {
+ return real_ioctl(s, r, p);
+ }
+
+ ret = real_ioctl(s, r, p);
+
+ switch (r) {
+ case FIONREAD:
+ value = *((int *)p);
+ if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
+ swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ } else if (value == 0) { /* END OF FILE */
+ swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ }
+ break;
+ }
+
+ return ret;
+}
+
+_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_recv(s, buf, len, flags);
+ }
+
+ ret = real_recv(s, buf, len, flags);
+ if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
+ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else if (ret == 0) { /* END OF FILE */
+ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else {
+ swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+ }
+
+ return ret;
+}
+
+
+_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_send(s, buf, len, flags);
+ }
+
+ ret = real_send(s, buf, len, flags);
+
+ if (ret == -1) {
+ swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+ swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
+ } else {
+ swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_close(int fd)
+{
+ struct socket_info *si = find_socket_info(fd);
+ int ret;
+
+ if (!si) {
+ return real_close(fd);
+ }
+
+ SWRAP_DLIST_REMOVE(sockets, si);
+
+ if (si->myname && si->peername) {
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
+ }
+
+ ret = real_close(fd);
+
+ if (si->myname && si->peername) {
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
+ }
+
+ if (si->path) free(si->path);
+ if (si->myname) free(si->myname);
+ if (si->peername) free(si->peername);
+ if (si->tmp_path) {
+ unlink(si->tmp_path);
+ free(si->tmp_path);
+ }
+ free(si);
+
+ return ret;
+}
diff --git a/source/lib/socket_wrapper/socket_wrapper.h b/source/lib/socket_wrapper/socket_wrapper.h
new file mode 100644
index 00000000000..1d8dac17632
--- /dev/null
+++ b/source/lib/socket_wrapper/socket_wrapper.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
+ * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SOCKET_WRAPPER_H__
+#define __SOCKET_WRAPPER_H__
+
+int swrap_socket(int family, int type, int protocol);
+int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen);
+int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen);
+int swrap_listen(int s, int backlog);
+int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen);
+int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
+int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
+int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
+ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
+ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
+int swrap_ioctl(int s, int req, void *ptr);
+ssize_t swrap_recv(int s, void *buf, size_t len, int flags);
+ssize_t swrap_send(int s, const void *buf, size_t len, int flags);
+int swrap_close(int);
+
+#ifdef SOCKET_WRAPPER_REPLACE
+
+#ifdef accept
+#undef accept
+#endif
+#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen)
+
+#ifdef connect
+#undef connect
+#endif
+#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen)
+
+#ifdef bind
+#undef bind
+#endif
+#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen)
+
+#ifdef listen
+#undef listen
+#endif
+#define listen(s,blog) swrap_listen(s,blog)
+
+#ifdef getpeername
+#undef getpeername
+#endif
+#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen)
+
+#ifdef getsockname
+#undef getsockname
+#endif
+#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen)
+
+#ifdef getsockopt
+#undef getsockopt
+#endif
+#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen)
+
+#ifdef setsockopt
+#undef setsockopt
+#endif
+#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen)
+
+#ifdef recvfrom
+#undef recvfrom
+#endif
+#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen)
+
+#ifdef sendto
+#undef sendto
+#endif
+#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen)
+
+#ifdef ioctl
+#undef ioctl
+#endif
+#define ioctl(s,req,ptr) swrap_ioctl(s,req,ptr)
+
+#ifdef recv
+#undef recv
+#endif
+#define recv(s,buf,len,flags) swrap_recv(s,buf,len,flags)
+
+#ifdef send
+#undef send
+#endif
+#define send(s,buf,len,flags) swrap_send(s,buf,len,flags)
+
+#ifdef socket
+#undef socket
+#endif
+#define socket(domain,type,protocol) swrap_socket(domain,type,protocol)
+
+#ifdef close
+#undef close
+#endif
+#define close(s) swrap_close(s)
+#endif
+
+#endif /* __SOCKET_WRAPPER_H__ */
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index ff9deb8a5f0..4c81bd8444e 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -415,11 +415,12 @@ static const char *automount_server(const char *user_name)
don't allow expansions.
****************************************************************************/
-void standard_sub_basic(const char *smb_name, char *str, size_t len)
+void standard_sub_basic(const char *smb_name, const char *domain_name,
+ char *str, size_t len)
{
char *s;
- if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) {
+ if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) {
strncpy( str, s, len );
}
@@ -432,11 +433,12 @@ void standard_sub_basic(const char *smb_name, char *str, size_t len)
This function will return an allocated string that have to be freed.
****************************************************************************/
-char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str)
+char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name,
+ const char *domain_name, const char *str)
{
char *a, *t;
- if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) {
+ if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) {
return NULL;
}
t = talloc_strdup(mem_ctx, a);
@@ -447,7 +449,8 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *st
/****************************************************************************
****************************************************************************/
-char *alloc_sub_basic(const char *smb_name, const char *str)
+char *alloc_sub_basic(const char *smb_name, const char *domain_name,
+ const char *str)
{
char *b, *p, *s, *r, *a_string;
fstring pidstr;
@@ -463,7 +466,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
a_string = SMB_STRDUP(str);
if (a_string == NULL) {
- DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
+ DEBUG(0, ("alloc_sub_basic: Out of memory!\n"));
return NULL;
}
@@ -490,7 +493,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
}
break;
case 'D' :
- r = strdup_upper(current_user_info.domain);
+ r = strdup_upper(domain_name);
if (r == NULL) {
goto error;
}
@@ -522,7 +525,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
a_string = realloc_string_sub(a_string, "%R", remote_proto);
break;
case 'T' :
- a_string = realloc_string_sub(a_string, "%T", timestring(False));
+ a_string = realloc_string_sub(a_string, "%T", current_timestring(False));
break;
case 'a' :
a_string = realloc_string_sub(a_string, "%a", remote_arch);
@@ -580,32 +583,20 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
uid_t uid,
gid_t gid)
{
- char *a, *t;
- a = alloc_sub_specified(input_string, username, domain, uid, gid);
- if (!a) {
+ char *a_string;
+ char *ret_string = NULL;
+ char *b, *p, *s;
+ TALLOC_CTX *tmp_ctx;
+
+ if (!(tmp_ctx = talloc_new(mem_ctx))) {
+ DEBUG(0, ("talloc_new failed\n"));
return NULL;
}
- t = talloc_strdup(mem_ctx, a);
- SAFE_FREE(a);
- return t;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-char *alloc_sub_specified(const char *input_string,
- const char *username,
- const char *domain,
- uid_t uid,
- gid_t gid)
-{
- char *a_string, *ret_string;
- char *b, *p, *s;
- a_string = SMB_STRDUP(input_string);
+ a_string = talloc_strdup(tmp_ctx, input_string);
if (a_string == NULL) {
- DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
- return NULL;
+ DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
+ goto done;
}
for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
@@ -614,30 +605,42 @@ char *alloc_sub_specified(const char *input_string,
switch (*(p+1)) {
case 'U' :
- a_string = realloc_string_sub(a_string, "%U", username);
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%U", username);
break;
case 'u' :
- a_string = realloc_string_sub(a_string, "%u", username);
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%u", username);
break;
case 'G' :
if (gid != -1) {
- a_string = realloc_string_sub(a_string, "%G", gidtoname(gid));
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%G",
+ gidtoname(gid));
} else {
- a_string = realloc_string_sub(a_string, "%G", "NO_GROUP");
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string,
+ "%G", "NO_GROUP");
}
break;
case 'g' :
if (gid != -1) {
- a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%g",
+ gidtoname(gid));
} else {
- a_string = realloc_string_sub(a_string, "%g", "NO_GROUP");
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%g", "NO_GROUP");
}
break;
case 'D' :
- a_string = realloc_string_sub(a_string, "%D", domain);
+ a_string = talloc_string_sub(tmp_ctx, a_string,
+ "%D", domain);
break;
case 'N' :
- a_string = realloc_string_sub(a_string, "%N", automount_server(username));
+ a_string = talloc_string_sub(
+ tmp_ctx, a_string, "%N",
+ automount_server(username));
break;
default:
break;
@@ -645,42 +648,27 @@ char *alloc_sub_specified(const char *input_string,
p++;
if (a_string == NULL) {
- return NULL;
+ goto done;
}
}
- ret_string = alloc_sub_basic(username, a_string);
- SAFE_FREE(a_string);
- return ret_string;
-}
+ /* Watch out, using "mem_ctx" here, so all intermediate stuff goes
+ * away with the TALLOC_FREE(tmp_ctx) further down. */
-/****************************************************************************
-****************************************************************************/
+ ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string);
-char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
- int snum,
- const char *user,
- const char *connectpath,
- gid_t gid,
- const char *smb_name,
- const char *str)
-{
- char *a, *t;
- a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str);
- if (!a) {
- return NULL;
- }
- t = talloc_strdup(mem_ctx, a);
- SAFE_FREE(a);
- return t;
+ done:
+ TALLOC_FREE(tmp_ctx);
+ return ret_string;
}
/****************************************************************************
****************************************************************************/
-char *alloc_sub_advanced(int snum, const char *user,
- const char *connectpath, gid_t gid,
- const char *smb_name, const char *str)
+static char *alloc_sub_advanced(const char *servicename, const char *user,
+ const char *connectpath, gid_t gid,
+ const char *smb_name, const char *domain_name,
+ const char *str)
{
char *a_string, *ret_string;
char *b, *p, *s, *h;
@@ -707,7 +695,7 @@ char *alloc_sub_advanced(int snum, const char *user,
a_string = realloc_string_sub(a_string, "%P", connectpath);
break;
case 'S':
- a_string = realloc_string_sub(a_string, "%S", lp_servicename(snum));
+ a_string = realloc_string_sub(a_string, "%S", servicename);
break;
case 'g':
a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
@@ -724,7 +712,8 @@ char *alloc_sub_advanced(int snum, const char *user,
* "path =" string in [homes] and so needs the
* service name, not the username. */
case 'p':
- a_string = realloc_string_sub(a_string, "%p", automount_path(lp_servicename(snum)));
+ a_string = realloc_string_sub(a_string, "%p",
+ automount_path(servicename));
break;
default:
@@ -737,70 +726,64 @@ char *alloc_sub_advanced(int snum, const char *user,
}
}
- ret_string = alloc_sub_basic(smb_name, a_string);
+ ret_string = alloc_sub_basic(smb_name, domain_name, a_string);
SAFE_FREE(a_string);
return ret_string;
}
-/****************************************************************************
- Do some standard substitutions in a string.
-****************************************************************************/
+/*
+ * This obviously is inefficient and needs to be merged into
+ * alloc_sub_advanced...
+ */
-void standard_sub_conn(connection_struct *conn, char *str, size_t len)
+char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
+ const char *servicename, const char *user,
+ const char *connectpath, gid_t gid,
+ const char *smb_name, const char *domain_name,
+ const char *str)
{
- char *s;
-
- s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
- conn->gid, smb_user_name, str);
+ char *a, *t;
- if ( s ) {
- strncpy( str, s, len );
- SAFE_FREE( s );
+ if (!(a = alloc_sub_advanced(servicename, user, connectpath, gid,
+ smb_name, domain_name, str))) {
+ return NULL;
}
+ t = talloc_strdup(mem_ctx, a);
+ SAFE_FREE(a);
+ return t;
}
-/****************************************************************************
-****************************************************************************/
-char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str)
+void standard_sub_advanced(const char *servicename, const char *user,
+ const char *connectpath, gid_t gid,
+ const char *smb_name, const char *domain_name,
+ char *str, size_t len)
{
- return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
- conn->connectpath, conn->gid,
- smb_user_name, str);
-}
-
-/****************************************************************************
-****************************************************************************/
+ char *s;
+
+ s = alloc_sub_advanced(servicename, user, connectpath,
+ gid, smb_name, domain_name, str);
-char *alloc_sub_conn(connection_struct *conn, const char *str)
-{
- return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
- conn->gid, smb_user_name, str);
+ if ( s ) {
+ strncpy( str, s, len );
+ SAFE_FREE( s );
+ }
}
/****************************************************************************
- Like standard_sub but by snum.
-****************************************************************************/
+ * Do some standard substitutions in a string.
+ * ****************************************************************************/
-void standard_sub_snum(int snum, char *str, size_t len)
+void standard_sub_conn(connection_struct *conn, char *str, size_t len)
{
- static uid_t cached_uid = -1;
- static fstring cached_user;
char *s;
-
- /* calling uidtoname() on every substitute would be too expensive, so
- we cache the result here as nearly every call is for the same uid */
-
- if (cached_uid != current_user.ut.uid) {
- fstrcpy(cached_user, uidtoname(current_user.ut.uid));
- cached_uid = current_user.ut.uid;
- }
- s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid,
- smb_user_name, str);
+ s = alloc_sub_advanced(lp_servicename(SNUM(conn)), conn->user, conn->connectpath,
+ conn->gid, smb_user_name, "", str);
if ( s ) {
strncpy( str, s, len );
SAFE_FREE( s );
}
}
+
diff --git a/source/lib/sysacls.c b/source/lib/sysacls.c
index 36baf96016c..d31c1870c34 100644
--- a/source/lib/sysacls.c
+++ b/source/lib/sysacls.c
@@ -2,6 +2,8 @@
Unix SMB/CIFS implementation.
Samba system utilities for ACL support.
Copyright (C) Jeremy Allison 2000.
+ Copyright (C) Volker Lendecke 2006
+ Copyright (C) Michael Adam 2006
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,337 +26,6 @@
#define DBGC_CLASS DBGC_ACLS
/*
- This file wraps all differing system ACL interfaces into a consistent
- one based on the POSIX interface. It also returns the correct errors
- for older UNIX systems that don't support ACLs.
-
- The interfaces that each ACL implementation must support are as follows :
-
- int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
- int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
- int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
- void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
- SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
- SMB_ACL_T sys_acl_get_fd(int fd)
- int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
- int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
- char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
- SMB_ACL_T sys_acl_init( int count)
- int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
- int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
- int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
- int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
- int sys_acl_valid( SMB_ACL_T theacl )
- int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
- int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
- int sys_acl_delete_def_file(const char *path)
-
- This next one is not POSIX complient - but we *have* to have it !
- More POSIX braindamage.
-
- int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-
- The generic POSIX free is the following call. We split this into
- several different free functions as we may need to add tag info
- to structures when emulating the POSIX interface.
-
- int sys_acl_free( void *obj_p)
-
- The calls we actually use are :
-
- int sys_acl_free_text(char *text) - free acl_to_text
- int sys_acl_free_acl(SMB_ACL_T posix_acl)
- int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
-
-*/
-
-#if defined(HAVE_POSIX_ACLS)
-
-/* Identity mapping - easy. */
-
-int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
- return acl_get_entry( the_acl, entry_id, entry_p);
-}
-
-int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
-{
- return acl_get_tag_type( entry_d, tag_type_p);
-}
-
-int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- return acl_get_permset( entry_d, permset_p);
-}
-
-void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
-{
- return acl_get_qualifier( entry_d);
-}
-
-SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
-{
- return acl_get_file( path_p, type);
-}
-
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- return acl_get_fd(fd);
-}
-
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
-{
- return acl_clear_perms(permset);
-}
-
-int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- return acl_add_perm(permset, perm);
-}
-
-int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
-#if defined(HAVE_ACL_GET_PERM_NP)
- /*
- * Required for TrustedBSD-based ACL implementations where
- * non-POSIX.1e functions are denoted by a _np (non-portable)
- * suffix.
- */
- return acl_get_perm_np(permset, perm);
-#else
- return acl_get_perm(permset, perm);
-#endif
-}
-
-char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
-{
- return acl_to_text( the_acl, plen);
-}
-
-SMB_ACL_T sys_acl_init( int count)
-{
- return acl_init(count);
-}
-
-int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
- return acl_create_entry(pacl, pentry);
-}
-
-int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
- return acl_set_tag_type(entry, tagtype);
-}
-
-int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
-{
- return acl_set_qualifier(entry, qual);
-}
-
-int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
- return acl_set_permset(entry, permset);
-}
-
-int sys_acl_valid( SMB_ACL_T theacl )
-{
- return acl_valid(theacl);
-}
-
-int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
-{
- return acl_set_file(name, acltype, theacl);
-}
-
-int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
-{
- return acl_set_fd(fd, theacl);
-}
-
-int sys_acl_delete_def_file(const char *name)
-{
- return acl_delete_def_file(name);
-}
-
-int sys_acl_free_text(char *text)
-{
- return acl_free(text);
-}
-
-int sys_acl_free_acl(SMB_ACL_T the_acl)
-{
- return acl_free(the_acl);
-}
-
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
-{
- return acl_free(qual);
-}
-
-#elif defined(HAVE_TRU64_ACLS)
-/*
- * The interface to DEC/Compaq Tru64 UNIX ACLs
- * is based on Draft 13 of the POSIX spec which is
- * slightly different from the Draft 16 interface.
- *
- * Also, some of the permset manipulation functions
- * such as acl_clear_perm() and acl_add_perm() appear
- * to be broken on Tru64 so we have to manipulate
- * the permission bits in the permset directly.
- */
-int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
- SMB_ACL_ENTRY_T entry;
-
- if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
- return -1;
- }
-
- errno = 0;
- if ((entry = acl_get_entry(the_acl)) != NULL) {
- *entry_p = entry;
- return 1;
- }
-
- return errno ? -1 : 0;
-}
-
-int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
-{
- return acl_get_tag_type( entry_d, tag_type_p);
-}
-
-int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- return acl_get_permset( entry_d, permset_p);
-}
-
-void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
-{
- return acl_get_qualifier( entry_d);
-}
-
-SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
-{
- return acl_get_file((char *)path_p, type);
-}
-
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- return acl_get_fd(fd, ACL_TYPE_ACCESS);
-}
-
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
-{
- *permset = 0; /* acl_clear_perm() is broken on Tru64 */
-
- return 0;
-}
-
-int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
- errno = EINVAL;
- return -1;
- }
-
- *permset |= perm; /* acl_add_perm() is broken on Tru64 */
-
- return 0;
-}
-
-int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
-}
-
-char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
-{
- return acl_to_text( the_acl, plen);
-}
-
-SMB_ACL_T sys_acl_init( int count)
-{
- return acl_init(count);
-}
-
-int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
- SMB_ACL_ENTRY_T entry;
-
- if ((entry = acl_create_entry(pacl)) == NULL) {
- return -1;
- }
-
- *pentry = entry;
- return 0;
-}
-
-int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
- return acl_set_tag_type(entry, tagtype);
-}
-
-int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
-{
- return acl_set_qualifier(entry, qual);
-}
-
-int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
- return acl_set_permset(entry, permset);
-}
-
-int sys_acl_valid( SMB_ACL_T theacl )
-{
- acl_entry_t entry;
-
- return acl_valid(theacl, &entry);
-}
-
-int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
-{
- return acl_set_file((char *)name, acltype, theacl);
-}
-
-int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
-{
- return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
-}
-
-int sys_acl_delete_def_file(const char *name)
-{
- return acl_delete_def_file((char *)name);
-}
-
-int sys_acl_free_text(char *text)
-{
- /*
- * (void) cast and explicit return 0 are for DEC UNIX
- * which just #defines acl_free_text() to be free()
- */
- (void) acl_free_text(text);
- return 0;
-}
-
-int sys_acl_free_acl(SMB_ACL_T the_acl)
-{
- return acl_free(the_acl);
-}
-
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
-{
- return acl_free_qualifier(qual, tagtype);
-}
-
-#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
-
-/*
- * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
- * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
- */
-
-/*
* Note that while this code implements sufficient functionality
* to support the sys_acl_* interfaces it does not provide all
* of the semantics of the POSIX ACL interfaces.
@@ -369,19 +40,6 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
* sys_acl_set_fd()
*/
-/*
- * The only difference between Solaris and UnixWare / OpenUNIX is
- * that the #defines for the ACL operations have different names
- */
-#if defined(HAVE_UNIXWARE_ACLS)
-
-#define SETACL ACL_SET
-#define GETACL ACL_GET
-#define GETACLCNT ACL_CNT
-
-#endif
-
-
int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
{
if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
@@ -428,148 +86,16 @@ int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
{
- if (entry_d->a_type != SMB_ACL_USER
- && entry_d->a_type != SMB_ACL_GROUP) {
- errno = EINVAL;
- return NULL;
- }
-
- return &entry_d->a_id;
-}
-
-/*
- * There is no way of knowing what size the ACL returned by
- * GETACL will be unless you first call GETACLCNT which means
- * making an additional system call.
- *
- * In the hope of avoiding the cost of the additional system
- * call in most cases, we initially allocate enough space for
- * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
- * be too small then we use GETACLCNT to find out the actual
- * size, reallocate the ACL buffer, and then call GETACL again.
- */
-
-#define INITIAL_ACL_SIZE 16
-
-SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
-{
- SMB_ACL_T acl_d;
- int count; /* # of ACL entries allocated */
- int naccess; /* # of access ACL entries */
- int ndefault; /* # of default ACL entries */
-
- if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
- errno = EINVAL;
- return NULL;
- }
-
- count = INITIAL_ACL_SIZE;
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
-
- /*
- * If there isn't enough space for the ACL entries we use
- * GETACLCNT to determine the actual number of ACL entries
- * reallocate and try again. This is in a loop because it
- * is possible that someone else could modify the ACL and
- * increase the number of entries between the call to
- * GETACLCNT and the call to GETACL.
- */
- while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
- && errno == ENOSPC) {
-
- sys_acl_free_acl(acl_d);
-
- if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
- return NULL;
- }
-
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
- }
-
- if (count < 0) {
- sys_acl_free_acl(acl_d);
- return NULL;
- }
-
- /*
- * calculate the number of access and default ACL entries
- *
- * Note: we assume that the acl() system call returned a
- * well formed ACL which is sorted so that all of the
- * access ACL entries preceed any default ACL entries
- */
- for (naccess = 0; naccess < count; naccess++) {
- if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
- break;
- }
- ndefault = count - naccess;
-
- /*
- * if the caller wants the default ACL we have to copy
- * the entries down to the start of the acl[] buffer
- * and mask out the ACL_DEFAULT flag from the type field
- */
- if (type == SMB_ACL_TYPE_DEFAULT) {
- int i, j;
-
- for (i = 0, j = naccess; i < ndefault; i++, j++) {
- acl_d->acl[i] = acl_d->acl[j];
- acl_d->acl[i].a_type &= ~ACL_DEFAULT;
- }
-
- acl_d->count = ndefault;
- } else {
- acl_d->count = naccess;
- }
-
- return acl_d;
-}
-
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- SMB_ACL_T acl_d;
- int count; /* # of ACL entries allocated */
- int naccess; /* # of access ACL entries */
-
- count = INITIAL_ACL_SIZE;
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
-
- while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
- && errno == ENOSPC) {
-
- sys_acl_free_acl(acl_d);
-
- if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
- return NULL;
+ if (entry_d->a_type == SMB_ACL_USER) {
+ return &entry_d->uid;
}
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
+ if (entry_d->a_type == SMB_ACL_GROUP) {
+ return &entry_d->gid;
}
- if (count < 0) {
- sys_acl_free_acl(acl_d);
+ errno = EINVAL;
return NULL;
- }
-
- /*
- * calculate the number of access ACL entries
- */
- for (naccess = 0; naccess < count; naccess++) {
- if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
- break;
- }
-
- acl_d->count = naccess;
-
- return acl_d;
}
int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
@@ -585,15 +111,15 @@ int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
&& perm != SMB_ACL_EXECUTE) {
errno = EINVAL;
return -1;
- }
-
+ }
+
if (permset_d == NULL) {
errno = EINVAL;
return -1;
}
*permset_d |= perm;
-
+
return 0;
}
@@ -615,19 +141,18 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
*/
len = 0;
maxlen = 20 * acl_d->count;
- if ((text = SMB_MALLOC(maxlen)) == NULL) {
+ if ((text = (char *)SMB_MALLOC(maxlen)) == NULL) {
errno = ENOMEM;
return NULL;
}
for (i = 0; i < acl_d->count; i++) {
- struct acl *ap = &acl_d->acl[i];
- struct passwd *pw;
+ struct smb_acl_entry *ap = &acl_d->acl[i];
struct group *gr;
char tagbuf[12];
char idbuf[12];
- char *tag;
- char *id = "";
+ const char *tag;
+ const char *id = "";
char perms[4];
int nbytes;
@@ -639,27 +164,24 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
*/
default:
slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
- ap->a_type);
+ ap->a_type);
tag = tagbuf;
- slprintf(idbuf, sizeof(idbuf)-1, "%ld",
- (long)ap->a_id);
- id = idbuf;
break;
-
+
case SMB_ACL_USER:
- id = uidtoname(ap->a_id);
+ id = uidtoname(ap->uid);
case SMB_ACL_USER_OBJ:
tag = "user";
break;
case SMB_ACL_GROUP:
- if ((gr = getgrgid(ap->a_id)) == NULL) {
+ if ((gr = getgrgid(ap->gid)) == NULL) {
slprintf(idbuf, sizeof(idbuf)-1, "%ld",
- (long)ap->a_id);
+ (long)ap->gid);
id = idbuf;
} else {
id = gr->gr_name;
- }
+ }
case SMB_ACL_GROUP_OBJ:
tag = "group";
break;
@@ -690,11 +212,11 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
*/
if ((len + nbytes) > maxlen) {
maxlen += nbytes + 20 * (acl_d->count - i);
- if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
- errno = ENOMEM;
+ if ((text = (char *)SMB_REALLOC(text, maxlen)) == NULL) {
+ errno = ENOMEM;
return NULL;
- }
}
+ }
slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
len += nbytes - 1;
@@ -721,11 +243,13 @@ SMB_ACL_T sys_acl_init(int count)
* acl[] array, this actually allocates an ACL with room
* for (count+1) entries
*/
- if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
+ if ((a = (struct smb_acl_t *)SMB_MALLOC(
+ sizeof(struct smb_acl_t) +
+ count * sizeof(struct smb_acl_entry))) == NULL) {
errno = ENOMEM;
return NULL;
}
-
+
a->size = count + 1;
a->count = 0;
a->next = -1;
@@ -733,7 +257,6 @@ SMB_ACL_T sys_acl_init(int count)
return a;
}
-
int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
{
SMB_ACL_T acl_d;
@@ -750,8 +273,9 @@ int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
}
entry_d = &acl_d->acl[acl_d->count++];
- entry_d->a_type = 0;
- entry_d->a_id = -1;
+ entry_d->a_type = SMB_ACL_TAG_INVALID;
+ entry_d->uid = -1;
+ entry_d->gid = -1;
entry_d->a_perm = 0;
*entry_p = entry_d;
@@ -772,184 +296,36 @@ int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
default:
errno = EINVAL;
return -1;
- }
+ }
return 0;
}
int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
{
- if (entry_d->a_type != SMB_ACL_GROUP
- && entry_d->a_type != SMB_ACL_USER) {
- errno = EINVAL;
- return -1;
+ if (entry_d->a_type == SMB_ACL_USER) {
+ entry_d->uid = *((uid_t *)qual_p);
+ return 0;
+ }
+ if (entry_d->a_type == SMB_ACL_GROUP) {
+ entry_d->gid = *((gid_t *)qual_p);
+ return 0;
}
- entry_d->a_id = *((id_t *)qual_p);
-
- return 0;
+ errno = EINVAL;
+ return -1;
}
int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
{
if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
- return EINVAL;
- }
-
- entry_d->a_perm = *permset_d;
-
- return 0;
-}
-
-/*
- * sort the ACL and check it for validity
- *
- * if it's a minimal ACL with only 4 entries then we
- * need to recalculate the mask permissions to make
- * sure that they are the same as the GROUP_OBJ
- * permissions as required by the UnixWare acl() system call.
- *
- * (note: since POSIX allows minimal ACLs which only contain
- * 3 entries - ie there is no mask entry - we should, in theory,
- * check for this and add a mask entry if necessary - however
- * we "know" that the caller of this interface always specifies
- * a mask so, in practice "this never happens" (tm) - if it *does*
- * happen aclsort() will fail and return an error and someone will
- * have to fix it ...)
- */
-
-static int acl_sort(SMB_ACL_T acl_d)
-{
- int fixmask = (acl_d->count <= 4);
-
- if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
errno = EINVAL;
return -1;
}
- return 0;
-}
-
-int sys_acl_valid(SMB_ACL_T acl_d)
-{
- return acl_sort(acl_d);
-}
-
-int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
-{
- struct stat s;
- struct acl *acl_p;
- int acl_count;
- struct acl *acl_buf = NULL;
- int ret;
-
- if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_sort(acl_d) != 0) {
- return -1;
- }
-
- acl_p = &acl_d->acl[0];
- acl_count = acl_d->count;
-
- /*
- * if it's a directory there is extra work to do
- * since the acl() system call will replace both
- * the access ACLs and the default ACLs (if any)
- */
- if (stat(name, &s) != 0) {
- return -1;
- }
- if (S_ISDIR(s.st_mode)) {
- SMB_ACL_T acc_acl;
- SMB_ACL_T def_acl;
- SMB_ACL_T tmp_acl;
- int i;
-
- if (type == SMB_ACL_TYPE_ACCESS) {
- acc_acl = acl_d;
- def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
-
- } else {
- def_acl = acl_d;
- acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
- }
-
- if (tmp_acl == NULL) {
- return -1;
- }
-
- /*
- * allocate a temporary buffer for the complete ACL
- */
- acl_count = acc_acl->count + def_acl->count;
- acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
-
- if (acl_buf == NULL) {
- sys_acl_free_acl(tmp_acl);
- errno = ENOMEM;
- return -1;
- }
-
- /*
- * copy the access control and default entries into the buffer
- */
- memcpy(&acl_buf[0], &acc_acl->acl[0],
- acc_acl->count * sizeof(acl_buf[0]));
-
- memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
- def_acl->count * sizeof(acl_buf[0]));
-
- /*
- * set the ACL_DEFAULT flag on the default entries
- */
- for (i = acc_acl->count; i < acl_count; i++) {
- acl_buf[i].a_type |= ACL_DEFAULT;
- }
-
- sys_acl_free_acl(tmp_acl);
-
- } else if (type != SMB_ACL_TYPE_ACCESS) {
- errno = EINVAL;
- return -1;
- }
-
- ret = acl(name, SETACL, acl_count, acl_p);
-
- SAFE_FREE(acl_buf);
-
- return ret;
-}
-
-int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
-{
- if (acl_sort(acl_d) != 0) {
- return -1;
- }
-
- return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
-}
-int sys_acl_delete_def_file(const char *path)
-{
- SMB_ACL_T acl_d;
- int ret;
-
- /*
- * fetching the access ACL and rewriting it has
- * the effect of deleting the default ACL
- */
- if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
- return -1;
- }
-
- ret = acl(path, SETACL, acl_d->count, acl_d->acl);
-
- sys_acl_free_acl(acl_d);
-
- return ret;
+ entry_d->a_perm = *permset_d;
+
+ return 0;
}
int sys_acl_free_text(char *text)
@@ -969,2231 +345,261 @@ int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
return 0;
}
-#elif defined(HAVE_HPUX_ACLS)
-#include <dl.h>
-
-/*
- * Based on the Solaris/SCO code - with modifications.
- */
-
-/*
- * Note that while this code implements sufficient functionality
- * to support the sys_acl_* interfaces it does not provide all
- * of the semantics of the POSIX ACL interfaces.
- *
- * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
- * from a call to sys_acl_get_entry() should not be assumed to be
- * valid after calling any of the following functions, which may
- * reorder the entries in the ACL.
- *
- * sys_acl_valid()
- * sys_acl_set_file()
- * sys_acl_set_fd()
- */
-
-/* This checks if the POSIX ACL system call is defined */
-/* which basically corresponds to whether JFS 3.3 or */
-/* higher is installed. If acl() was called when it */
-/* isn't defined, it causes the process to core dump */
-/* so it is important to check this and avoid acl() */
-/* calls if it isn't there. */
-
-static BOOL hpux_acl_call_presence(void)
-{
-
- shl_t handle = NULL;
- void *value;
- int ret_val=0;
- static BOOL already_checked=0;
-
- if(already_checked)
- return True;
-
-
- ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
-
- if(ret_val != 0) {
- DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
- ret_val, errno, strerror(errno)));
- DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
- return False;
- }
-
- DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
-
- already_checked = True;
- return True;
-}
-
-int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
- if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
- errno = EINVAL;
- return -1;
- }
-
- if (entry_p == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (entry_id == SMB_ACL_FIRST_ENTRY) {
- acl_d->next = 0;
- }
-
- if (acl_d->next < 0) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_d->next >= acl_d->count) {
- return 0;
- }
-
- *entry_p = &acl_d->acl[acl_d->next++];
-
- return 1;
-}
-
-int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
-{
- *type_p = entry_d->a_type;
-
- return 0;
-}
-
-int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- *permset_p = &entry_d->a_perm;
-
- return 0;
-}
-
-void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
+int sys_acl_valid(SMB_ACL_T acl_d)
{
- if (entry_d->a_type != SMB_ACL_USER
- && entry_d->a_type != SMB_ACL_GROUP) {
- errno = EINVAL;
- return NULL;
- }
-
- return &entry_d->a_id;
+ errno = EINVAL;
+ return -1;
}
/*
- * There is no way of knowing what size the ACL returned by
- * ACL_GET will be unless you first call ACL_CNT which means
- * making an additional system call.
- *
- * In the hope of avoiding the cost of the additional system
- * call in most cases, we initially allocate enough space for
- * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
- * be too small then we use ACL_CNT to find out the actual
- * size, reallocate the ACL buffer, and then call ACL_GET again.
- */
-
-#define INITIAL_ACL_SIZE 16
-
-SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
-{
- SMB_ACL_T acl_d;
- int count; /* # of ACL entries allocated */
- int naccess; /* # of access ACL entries */
- int ndefault; /* # of default ACL entries */
-
- if(hpux_acl_call_presence() == False) {
- /* Looks like we don't have the acl() system call on HPUX.
- * May be the system doesn't have the latest version of JFS.
- */
- return NULL;
- }
-
- if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
- errno = EINVAL;
- return NULL;
- }
-
- count = INITIAL_ACL_SIZE;
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
-
- /*
- * If there isn't enough space for the ACL entries we use
- * ACL_CNT to determine the actual number of ACL entries
- * reallocate and try again. This is in a loop because it
- * is possible that someone else could modify the ACL and
- * increase the number of entries between the call to
- * ACL_CNT and the call to ACL_GET.
- */
- while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
-
- sys_acl_free_acl(acl_d);
-
- if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
- return NULL;
- }
-
- if ((acl_d = sys_acl_init(count)) == NULL) {
- return NULL;
- }
- }
-
- if (count < 0) {
- sys_acl_free_acl(acl_d);
- return NULL;
- }
-
- /*
- * calculate the number of access and default ACL entries
- *
- * Note: we assume that the acl() system call returned a
- * well formed ACL which is sorted so that all of the
- * access ACL entries preceed any default ACL entries
- */
- for (naccess = 0; naccess < count; naccess++) {
- if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
- break;
- }
- ndefault = count - naccess;
-
- /*
- * if the caller wants the default ACL we have to copy
- * the entries down to the start of the acl[] buffer
- * and mask out the ACL_DEFAULT flag from the type field
- */
- if (type == SMB_ACL_TYPE_DEFAULT) {
- int i, j;
-
- for (i = 0, j = naccess; i < ndefault; i++, j++) {
- acl_d->acl[i] = acl_d->acl[j];
- acl_d->acl[i].a_type &= ~ACL_DEFAULT;
- }
-
- acl_d->count = ndefault;
- } else {
- acl_d->count = naccess;
- }
-
- return acl_d;
-}
-
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- /*
- * HPUX doesn't have the facl call. Fake it using the path.... JRA.
- */
-
- files_struct *fsp = file_find_fd(fd);
-
- if (fsp == NULL) {
- errno = EBADF;
- return NULL;
- }
-
- /*
- * We know we're in the same conn context. So we
- * can use the relative path.
- */
-
- return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
-}
-
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
-{
- *permset_d = 0;
-
- return 0;
-}
-
-int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
-{
- if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
- && perm != SMB_ACL_EXECUTE) {
- errno = EINVAL;
- return -1;
- }
-
- if (permset_d == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- *permset_d |= perm;
-
- return 0;
-}
-
-int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
-{
- return *permset_d & perm;
-}
-
-char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
-{
- int i;
- int len, maxlen;
- char *text;
-
- /*
- * use an initial estimate of 20 bytes per ACL entry
- * when allocating memory for the text representation
- * of the ACL
- */
- len = 0;
- maxlen = 20 * acl_d->count;
- if ((text = SMB_MALLOC(maxlen)) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
-
- for (i = 0; i < acl_d->count; i++) {
- struct acl *ap = &acl_d->acl[i];
- struct passwd *pw;
- struct group *gr;
- char tagbuf[12];
- char idbuf[12];
- char *tag;
- char *id = "";
- char perms[4];
- int nbytes;
-
- switch (ap->a_type) {
- /*
- * for debugging purposes it's probably more
- * useful to dump unknown tag types rather
- * than just returning an error
- */
- default:
- slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
- ap->a_type);
- tag = tagbuf;
- slprintf(idbuf, sizeof(idbuf)-1, "%ld",
- (long)ap->a_id);
- id = idbuf;
- break;
-
- case SMB_ACL_USER:
- id = uidtoname(ap->a_id);
- case SMB_ACL_USER_OBJ:
- tag = "user";
- break;
-
- case SMB_ACL_GROUP:
- if ((gr = getgrgid(ap->a_id)) == NULL) {
- slprintf(idbuf, sizeof(idbuf)-1, "%ld",
- (long)ap->a_id);
- id = idbuf;
- } else {
- id = gr->gr_name;
- }
- case SMB_ACL_GROUP_OBJ:
- tag = "group";
- break;
-
- case SMB_ACL_OTHER:
- tag = "other";
- break;
-
- case SMB_ACL_MASK:
- tag = "mask";
- break;
-
- }
-
- perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
- perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
- perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
- perms[3] = '\0';
-
- /* <tag> : <qualifier> : rwx \n \0 */
- nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
-
- /*
- * If this entry would overflow the buffer
- * allocate enough additional memory for this
- * entry and an estimate of another 20 bytes
- * for each entry still to be processed
- */
- if ((len + nbytes) > maxlen) {
- maxlen += nbytes + 20 * (acl_d->count - i);
- if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- }
-
- slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
- len += nbytes - 1;
- }
-
- if (len_p)
- *len_p = len;
-
- return text;
-}
-
-SMB_ACL_T sys_acl_init(int count)
-{
- SMB_ACL_T a;
-
- if (count < 0) {
- errno = EINVAL;
- return NULL;
- }
-
- /*
- * note that since the definition of the structure pointed
- * to by the SMB_ACL_T includes the first element of the
- * acl[] array, this actually allocates an ACL with room
- * for (count+1) entries
- */
- if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
-
- a->size = count + 1;
- a->count = 0;
- a->next = -1;
-
- return a;
-}
-
-
-int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
-{
- SMB_ACL_T acl_d;
- SMB_ACL_ENTRY_T entry_d;
-
- if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_d->count >= acl_d->size) {
- errno = ENOSPC;
- return -1;
- }
-
- entry_d = &acl_d->acl[acl_d->count++];
- entry_d->a_type = 0;
- entry_d->a_id = -1;
- entry_d->a_perm = 0;
- *entry_p = entry_d;
-
- return 0;
-}
-
-int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
-{
- switch (tag_type) {
- case SMB_ACL_USER:
- case SMB_ACL_USER_OBJ:
- case SMB_ACL_GROUP:
- case SMB_ACL_GROUP_OBJ:
- case SMB_ACL_OTHER:
- case SMB_ACL_MASK:
- entry_d->a_type = tag_type;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
-
- return 0;
-}
-
-int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
-{
- if (entry_d->a_type != SMB_ACL_GROUP
- && entry_d->a_type != SMB_ACL_USER) {
- errno = EINVAL;
- return -1;
- }
-
- entry_d->a_id = *((id_t *)qual_p);
-
- return 0;
-}
-
-int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
-{
- if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
- return EINVAL;
- }
-
- entry_d->a_perm = *permset_d;
-
- return 0;
-}
-
-/* Structure to capture the count for each type of ACE. */
-
-struct hpux_acl_types {
- int n_user;
- int n_def_user;
- int n_user_obj;
- int n_def_user_obj;
-
- int n_group;
- int n_def_group;
- int n_group_obj;
- int n_def_group_obj;
-
- int n_other;
- int n_other_obj;
- int n_def_other_obj;
-
- int n_class_obj;
- int n_def_class_obj;
-
- int n_illegal_obj;
-};
-
-/* count_obj:
- * Counts the different number of objects in a given array of ACL
- * structures.
- * Inputs:
- *
- * acl_count - Count of ACLs in the array of ACL strucutres.
- * aclp - Array of ACL structures.
- * acl_type_count - Pointer to acl_types structure. Should already be
- * allocated.
- * Output:
- *
- * acl_type_count - This structure is filled up with counts of various
- * acl types.
- */
-
-static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
-{
- int i;
-
- memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
-
- for(i=0;i<acl_count;i++) {
- switch(aclp[i].a_type) {
- case USER:
- acl_type_count->n_user++;
- break;
- case USER_OBJ:
- acl_type_count->n_user_obj++;
- break;
- case DEF_USER_OBJ:
- acl_type_count->n_def_user_obj++;
- break;
- case GROUP:
- acl_type_count->n_group++;
- break;
- case GROUP_OBJ:
- acl_type_count->n_group_obj++;
- break;
- case DEF_GROUP_OBJ:
- acl_type_count->n_def_group_obj++;
- break;
- case OTHER_OBJ:
- acl_type_count->n_other_obj++;
- break;
- case DEF_OTHER_OBJ:
- acl_type_count->n_def_other_obj++;
- break;
- case CLASS_OBJ:
- acl_type_count->n_class_obj++;
- break;
- case DEF_CLASS_OBJ:
- acl_type_count->n_def_class_obj++;
- break;
- case DEF_USER:
- acl_type_count->n_def_user++;
- break;
- case DEF_GROUP:
- acl_type_count->n_def_group++;
- break;
- default:
- acl_type_count->n_illegal_obj++;
- break;
- }
- }
-}
-
-/* swap_acl_entries: Swaps two ACL entries.
- *
- * Inputs: aclp0, aclp1 - ACL entries to be swapped.
+ * acl_get_file, acl_get_fd, acl_set_file, acl_set_fd and
+ * sys_acl_delete_def_file are to be redirected to the default
+ * statically-bound acl vfs module, but they are replacable.
*/
-
-static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
-{
- struct acl temp_acl;
-
- temp_acl.a_type = aclp0->a_type;
- temp_acl.a_id = aclp0->a_id;
- temp_acl.a_perm = aclp0->a_perm;
-
- aclp0->a_type = aclp1->a_type;
- aclp0->a_id = aclp1->a_id;
- aclp0->a_perm = aclp1->a_perm;
-
- aclp1->a_type = temp_acl.a_type;
- aclp1->a_id = temp_acl.a_id;
- aclp1->a_perm = temp_acl.a_perm;
-}
-
-/* prohibited_duplicate_type
- * Identifies if given ACL type can have duplicate entries or
- * not.
- *
- * Inputs: acl_type - ACL Type.
- *
- * Outputs:
- *
- * Return..
- *
- * True - If the ACL type matches any of the prohibited types.
- * False - If the ACL type doesn't match any of the prohibited types.
- */
-
-static BOOL hpux_prohibited_duplicate_type(int acl_type)
-{
- switch(acl_type) {
- case USER:
- case GROUP:
- case DEF_USER:
- case DEF_GROUP:
- return True;
- default:
- return False;
- }
-}
-
-/* get_needed_class_perm
- * Returns the permissions of a ACL structure only if the ACL
- * type matches one of the pre-determined types for computing
- * CLASS_OBJ permissions.
- *
- * Inputs: aclp - Pointer to ACL structure.
- */
-
-static int hpux_get_needed_class_perm(struct acl *aclp)
-{
- switch(aclp->a_type) {
- case USER:
- case GROUP_OBJ:
- case GROUP:
- case DEF_USER_OBJ:
- case DEF_USER:
- case DEF_GROUP_OBJ:
- case DEF_GROUP:
- case DEF_CLASS_OBJ:
- case DEF_OTHER_OBJ:
- return aclp->a_perm;
- default:
- return 0;
- }
-}
-
-/* acl_sort for HPUX.
- * Sorts the array of ACL structures as per the description in
- * aclsort man page. Refer to aclsort man page for more details
- *
- * Inputs:
- *
- * acl_count - Count of ACLs in the array of ACL structures.
- * calclass - If this is not zero, then we compute the CLASS_OBJ
- * permissions.
- * aclp - Array of ACL structures.
- *
- * Outputs:
- *
- * aclp - Sorted array of ACL structures.
- *
- * Outputs:
- *
- * Returns 0 for success -1 for failure. Prints a message to the Samba
- * debug log in case of failure.
- */
-
-static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
-{
-#if !defined(HAVE_HPUX_ACLSORT)
- /*
- * The aclsort() system call is availabe on the latest HPUX General
- * Patch Bundles. So for HPUX, we developed our version of acl_sort
- * function. Because, we don't want to update to a new
- * HPUX GR bundle just for aclsort() call.
- */
-
- struct hpux_acl_types acl_obj_count;
- int n_class_obj_perm = 0;
- int i, j;
- if(!acl_count) {
- DEBUG(10,("Zero acl count passed. Returning Success\n"));
- return 0;
- }
-
- if(aclp == NULL) {
- DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
- return -1;
- }
-
- /* Count different types of ACLs in the ACLs array */
-
- hpux_count_obj(acl_count, aclp, &acl_obj_count);
-
- /* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
- * CLASS_OBJ and OTHER_OBJ
- */
-
- if( (acl_obj_count.n_user_obj != 1) ||
- (acl_obj_count.n_group_obj != 1) ||
- (acl_obj_count.n_class_obj != 1) ||
- (acl_obj_count.n_other_obj != 1)
- ) {
- DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
-USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
- return -1;
- }
-
- /* If any of the default objects are present, there should be only
- * one of them each.
- */
-
- if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) ||
- (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
- DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
-or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
- return -1;
- }
-
- /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
- * structures.
- *
- * Sorting crieteria - First sort by ACL type. If there are multiple entries of
- * same ACL type, sort by ACL id.
- *
- * I am using the trival kind of sorting method here because, performance isn't
- * really effected by the ACLs feature. More over there aren't going to be more
- * than 17 entries on HPUX.
- */
-
- for(i=0; i<acl_count;i++) {
- for (j=i+1; j<acl_count; j++) {
- if( aclp[i].a_type > aclp[j].a_type ) {
- /* ACL entries out of order, swap them */
-
- hpux_swap_acl_entries((aclp+i), (aclp+j));
-
- } else if ( aclp[i].a_type == aclp[j].a_type ) {
-
- /* ACL entries of same type, sort by id */
-
- if(aclp[i].a_id > aclp[j].a_id) {
- hpux_swap_acl_entries((aclp+i), (aclp+j));
- } else if (aclp[i].a_id == aclp[j].a_id) {
- /* We have a duplicate entry. */
- if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
- DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
- aclp[i].a_type, aclp[i].a_id));
- return -1;
- }
- }
-
- }
- }
- }
-
- /* set the class obj permissions to the computed one. */
- if(calclass) {
- int n_class_obj_index = -1;
-
- for(i=0;i<acl_count;i++) {
- n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
-
- if(aclp[i].a_type == CLASS_OBJ)
- n_class_obj_index = i;
- }
- aclp[n_class_obj_index].a_perm = n_class_obj_perm;
- }
-
- return 0;
-#else
- return aclsort(acl_count, calclass, aclp);
-#endif
-}
-
-/*
- * sort the ACL and check it for validity
- *
- * if it's a minimal ACL with only 4 entries then we
- * need to recalculate the mask permissions to make
- * sure that they are the same as the GROUP_OBJ
- * permissions as required by the UnixWare acl() system call.
- *
- * (note: since POSIX allows minimal ACLs which only contain
- * 3 entries - ie there is no mask entry - we should, in theory,
- * check for this and add a mask entry if necessary - however
- * we "know" that the caller of this interface always specifies
- * a mask so, in practice "this never happens" (tm) - if it *does*
- * happen aclsort() will fail and return an error and someone will
- * have to fix it ...)
- */
-
-static int acl_sort(SMB_ACL_T acl_d)
-{
- int fixmask = (acl_d->count <= 4);
-
- if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
- errno = EINVAL;
- return -1;
- }
- return 0;
-}
+#if defined(HAVE_POSIX_ACLS)
-int sys_acl_valid(SMB_ACL_T acl_d)
-{
- return acl_sort(acl_d);
-}
-
-int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
-{
- struct stat s;
- struct acl *acl_p;
- int acl_count;
- struct acl *acl_buf = NULL;
- int ret;
-
- if(hpux_acl_call_presence() == False) {
- /* Looks like we don't have the acl() system call on HPUX.
- * May be the system doesn't have the latest version of JFS.
- */
- errno=ENOSYS;
- return -1;
- }
-
- if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_sort(acl_d) != 0) {
- return -1;
- }
-
- acl_p = &acl_d->acl[0];
- acl_count = acl_d->count;
-
- /*
- * if it's a directory there is extra work to do
- * since the acl() system call will replace both
- * the access ACLs and the default ACLs (if any)
- */
- if (stat(name, &s) != 0) {
- return -1;
- }
- if (S_ISDIR(s.st_mode)) {
- SMB_ACL_T acc_acl;
- SMB_ACL_T def_acl;
- SMB_ACL_T tmp_acl;
- int i;
-
- if (type == SMB_ACL_TYPE_ACCESS) {
- acc_acl = acl_d;
- def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
-
- } else {
- def_acl = acl_d;
- acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
- }
-
- if (tmp_acl == NULL) {
- return -1;
- }
-
- /*
- * allocate a temporary buffer for the complete ACL
- */
- acl_count = acc_acl->count + def_acl->count;
- acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
-
- if (acl_buf == NULL) {
- sys_acl_free_acl(tmp_acl);
- errno = ENOMEM;
- return -1;
- }
-
- /*
- * copy the access control and default entries into the buffer
- */
- memcpy(&acl_buf[0], &acc_acl->acl[0],
- acc_acl->count * sizeof(acl_buf[0]));
-
- memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
- def_acl->count * sizeof(acl_buf[0]));
-
- /*
- * set the ACL_DEFAULT flag on the default entries
- */
- for (i = acc_acl->count; i < acl_count; i++) {
- acl_buf[i].a_type |= ACL_DEFAULT;
- }
-
- sys_acl_free_acl(tmp_acl);
-
- } else if (type != SMB_ACL_TYPE_ACCESS) {
- errno = EINVAL;
- return -1;
- }
-
- ret = acl(name, ACL_SET, acl_count, acl_p);
-
- if (acl_buf) {
- free(acl_buf);
- }
-
- return ret;
-}
-
-int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
-{
- /*
- * HPUX doesn't have the facl call. Fake it using the path.... JRA.
- */
-
- files_struct *fsp = file_find_fd(fd);
-
- if (fsp == NULL) {
- errno = EBADF;
- return NULL;
- }
-
- if (acl_sort(acl_d) != 0) {
- return -1;
- }
-
- /*
- * We know we're in the same conn context. So we
- * can use the relative path.
- */
-
- return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
-}
-
-int sys_acl_delete_def_file(const char *path)
-{
- SMB_ACL_T acl_d;
- int ret;
-
- /*
- * fetching the access ACL and rewriting it has
- * the effect of deleting the default ACL
- */
- if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
- return -1;
- }
-
- ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
-
- sys_acl_free_acl(acl_d);
-
- return ret;
-}
-
-int sys_acl_free_text(char *text)
-{
- free(text);
- return 0;
-}
-
-int sys_acl_free_acl(SMB_ACL_T acl_d)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- free(acl_d);
- return 0;
+ return posixacl_sys_acl_get_file(handle, path_p, type);
}
-
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
-{
- return 0;
-}
-
-#elif defined(HAVE_IRIX_ACLS)
-
-int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
- if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
- errno = EINVAL;
- return -1;
- }
-
- if (entry_p == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (entry_id == SMB_ACL_FIRST_ENTRY) {
- acl_d->next = 0;
- }
-
- if (acl_d->next < 0) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_d->next >= acl_d->aclp->acl_cnt) {
- return 0;
- }
-
- *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
-
- return 1;
-}
-
-int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
-{
- *type_p = entry_d->ae_tag;
-
- return 0;
-}
-
-int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- *permset_p = entry_d;
-
- return 0;
-}
-
-void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
-{
- if (entry_d->ae_tag != SMB_ACL_USER
- && entry_d->ae_tag != SMB_ACL_GROUP) {
- errno = EINVAL;
- return NULL;
- }
-
- return &entry_d->ae_id;
-}
-
-SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
-{
- SMB_ACL_T a;
-
- if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
- SAFE_FREE(a);
- return NULL;
- }
- a->next = -1;
- a->freeaclp = True;
- return a;
-}
-
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- SMB_ACL_T a;
-
- if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- if ((a->aclp = acl_get_fd(fd)) == NULL) {
- SAFE_FREE(a);
- return NULL;
- }
- a->next = -1;
- a->freeaclp = True;
- return a;
-}
-
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
-{
- permset_d->ae_perm = 0;
-
- return 0;
-}
-
-int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
-{
- if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
- && perm != SMB_ACL_EXECUTE) {
- errno = EINVAL;
- return -1;
- }
-
- if (permset_d == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- permset_d->ae_perm |= perm;
-
- return 0;
-}
-
-int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
-{
- return permset_d->ae_perm & perm;
-}
-
-char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
-{
- return acl_to_text(acl_d->aclp, len_p);
-}
-
-SMB_ACL_T sys_acl_init(int count)
-{
- SMB_ACL_T a;
-
- if (count < 0) {
- errno = EINVAL;
- return NULL;
- }
-
- if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
-
- a->next = -1;
- a->freeaclp = False;
- a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
- a->aclp->acl_cnt = 0;
-
- return a;
-}
-
-
-int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
-{
- SMB_ACL_T acl_d;
- SMB_ACL_ENTRY_T entry_d;
-
- if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
- errno = ENOSPC;
- return -1;
- }
-
- entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
- entry_d->ae_tag = 0;
- entry_d->ae_id = 0;
- entry_d->ae_perm = 0;
- *entry_p = entry_d;
-
- return 0;
-}
-
-int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
-{
- switch (tag_type) {
- case SMB_ACL_USER:
- case SMB_ACL_USER_OBJ:
- case SMB_ACL_GROUP:
- case SMB_ACL_GROUP_OBJ:
- case SMB_ACL_OTHER:
- case SMB_ACL_MASK:
- entry_d->ae_tag = tag_type;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
-
- return 0;
-}
-
-int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
-{
- if (entry_d->ae_tag != SMB_ACL_GROUP
- && entry_d->ae_tag != SMB_ACL_USER) {
- errno = EINVAL;
- return -1;
- }
-
- entry_d->ae_id = *((id_t *)qual_p);
-
- return 0;
-}
-
-int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
-{
- if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
- return EINVAL;
- }
-
- entry_d->ae_perm = permset_d->ae_perm;
-
- return 0;
-}
-
-int sys_acl_valid(SMB_ACL_T acl_d)
-{
- return acl_valid(acl_d->aclp);
-}
-
-int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
-{
- return acl_set_file(name, type, acl_d->aclp);
-}
-
-int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
-{
- return acl_set_fd(fd, acl_d->aclp);
-}
-
-int sys_acl_delete_def_file(const char *name)
+
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- return acl_delete_def_file(name);
+ return posixacl_sys_acl_get_fd(handle, fsp, fd);
}
-
-int sys_acl_free_text(char *text)
+
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- return acl_free(text);
+ return posixacl_sys_acl_set_file(handle, name, type, acl_d);
}
-
-int sys_acl_free_acl(SMB_ACL_T acl_d)
+
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- if (acl_d->freeaclp) {
- acl_free(acl_d->aclp);
- }
- acl_free(acl_d);
- return 0;
+ return posixacl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- return 0;
+ return posixacl_sys_acl_delete_def_file(handle, path);
}
#elif defined(HAVE_AIX_ACLS)
-/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
-
-int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- struct acl_entry_link *link;
- struct new_acl_entry *entry;
- int keep_going;
-
- DEBUG(10,("This is the count: %d\n",theacl->count));
-
- /* Check if count was previously set to -1. *
- * If it was, that means we reached the end *
- * of the acl last time. */
- if(theacl->count == -1)
- return(0);
-
- link = theacl;
- /* To get to the next acl, traverse linked list until index *
- * of acl matches the count we are keeping. This count is *
- * incremented each time we return an acl entry. */
-
- for(keep_going = 0; keep_going < theacl->count; keep_going++)
- link = link->nextp;
-
- entry = *entry_p = link->entryp;
-
- DEBUG(10,("*entry_p is %d\n",entry_p));
- DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
-
- /* Increment count */
- theacl->count++;
- if(link->nextp == NULL)
- theacl->count = -1;
-
- return(1);
+ return aixacl_sys_acl_get_file(handle, path_p, type);
}
-int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- /* Initialize tag type */
-
- *tag_type_p = -1;
- DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
-
- /* Depending on what type of entry we have, *
- * return tag type. */
- switch(entry_d->ace_id->id_type) {
- case ACEID_USER:
- *tag_type_p = SMB_ACL_USER;
- break;
- case ACEID_GROUP:
- *tag_type_p = SMB_ACL_GROUP;
- break;
-
- case SMB_ACL_USER_OBJ:
- case SMB_ACL_GROUP_OBJ:
- case SMB_ACL_OTHER:
- *tag_type_p = entry_d->ace_id->id_type;
- break;
-
- default:
- return(-1);
- }
-
- return(0);
+ return aixacl_sys_acl_get_fd(handle, fsp, fd);
}
-int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
- *permset_p = &entry_d->ace_access;
- DEBUG(10,("**permset_p is %d\n",**permset_p));
- if(!(**permset_p & S_IXUSR) &&
- !(**permset_p & S_IWUSR) &&
- !(**permset_p & S_IRUSR) &&
- (**permset_p != 0))
- return(-1);
-
- DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
- return(0);
+ return aixacl_sys_acl_set_file(handle, name, type, acl_d);
}
-void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- return(entry_d->ace_id->id_data);
+ return aixacl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- struct acl *file_acl = (struct acl *)NULL;
- struct acl_entry *acl_entry;
- struct new_acl_entry *new_acl_entry;
- struct ace_id *idp;
- struct acl_entry_link *acl_entry_link;
- struct acl_entry_link *acl_entry_link_head;
- int i;
- int rc = 0;
- uid_t user_id;
-
- /* AIX has no DEFAULT */
- if ( type == SMB_ACL_TYPE_DEFAULT )
- return NULL;
-
- /* Get the acl using statacl */
-
- DEBUG(10,("Entering sys_acl_get_file\n"));
- DEBUG(10,("path_p is %s\n",path_p));
-
- file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
-
- if(file_acl == NULL) {
- errno=ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
- return(NULL);
- }
-
- memset(file_acl,0,BUFSIZ);
-
- rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
- if(rc == -1) {
- DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- DEBUG(10,("Got facl and returned it\n"));
-
- /* Point to the first acl entry in the acl */
- acl_entry = file_acl->acl_ext;
-
- /* Begin setting up the head of the linked list *
- * that will be used for the storing the acl *
- * in a way that is useful for the posix_acls.c *
- * code. */
-
- acl_entry_link_head = acl_entry_link = sys_acl_init(0);
- if(acl_entry_link_head == NULL)
- return(NULL);
-
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
- if(acl_entry_link->entryp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
- return(NULL);
- }
-
- DEBUG(10,("acl_entry is %d\n",acl_entry));
- DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
-
- /* Check if the extended acl bit is on. *
- * If it isn't, do not show the *
- * contents of the acl since AIX intends *
- * the extended info to remain unused */
-
- if(file_acl->acl_mode & S_IXACL){
- /* while we are not pointing to the very end */
- while(acl_entry < acl_last(file_acl)) {
- /* before we malloc anything, make sure this is */
- /* a valid acl entry and one that we want to map */
- idp = id_nxt(acl_entry->ace_id);
- if((acl_entry->ace_type == ACC_SPECIFY ||
- (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
- acl_entry = acl_nxt(acl_entry);
- continue;
- }
-
- idp = acl_entry->ace_id;
-
- /* Check if this is the first entry in the linked list. *
- * The first entry needs to keep prevp pointing to NULL *
- * and already has entryp allocated. */
-
- if(acl_entry_link_head->count != 0) {
- acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
-
- if(acl_entry_link->nextp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
- return(NULL);
- }
-
- acl_entry_link->nextp->prevp = acl_entry_link;
- acl_entry_link = acl_entry_link->nextp;
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
- if(acl_entry_link->entryp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
- return(NULL);
- }
- acl_entry_link->nextp = NULL;
- }
-
- acl_entry_link->entryp->ace_len = acl_entry->ace_len;
-
- /* Don't really need this since all types are going *
- * to be specified but, it's better than leaving it 0 */
-
- acl_entry_link->entryp->ace_type = acl_entry->ace_type;
-
- acl_entry_link->entryp->ace_access = acl_entry->ace_access;
-
- memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
-
- /* The access in the acl entries must be left shifted by *
- * three bites, because they will ultimately be compared *
- * to S_IRUSR, S_IWUSR, and S_IXUSR. */
-
- switch(acl_entry->ace_type){
- case ACC_PERMIT:
- case ACC_SPECIFY:
- acl_entry_link->entryp->ace_access = acl_entry->ace_access;
- acl_entry_link->entryp->ace_access <<= 6;
- acl_entry_link_head->count++;
- break;
- case ACC_DENY:
- /* Since there is no way to return a DENY acl entry *
- * change to PERMIT and then shift. */
- DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
- acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
- DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
- acl_entry_link->entryp->ace_access <<= 6;
- acl_entry_link_head->count++;
- break;
- default:
- return(0);
- }
-
- DEBUG(10,("acl_entry = %d\n",acl_entry));
- DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
-
- acl_entry = acl_nxt(acl_entry);
- }
- } /* end of if enabled */
-
- /* Since owner, group, other acl entries are not *
- * part of the acl entries in an acl, they must *
- * be dummied up to become part of the list. */
-
- for( i = 1; i < 4; i++) {
- DEBUG(10,("i is %d\n",i));
- if(acl_entry_link_head->count != 0) {
- acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
- if(acl_entry_link->nextp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
- return(NULL);
- }
-
- acl_entry_link->nextp->prevp = acl_entry_link;
- acl_entry_link = acl_entry_link->nextp;
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
- if(acl_entry_link->entryp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
- return(NULL);
- }
- }
-
- acl_entry_link->nextp = NULL;
-
- new_acl_entry = acl_entry_link->entryp;
- idp = new_acl_entry->ace_id;
-
- new_acl_entry->ace_len = sizeof(struct acl_entry);
- new_acl_entry->ace_type = ACC_PERMIT;
- idp->id_len = sizeof(struct ace_id);
- DEBUG(10,("idp->id_len = %d\n",idp->id_len));
- memset(idp->id_data,0,sizeof(uid_t));
-
- switch(i) {
- case 2:
- new_acl_entry->ace_access = file_acl->g_access << 6;
- idp->id_type = SMB_ACL_GROUP_OBJ;
- break;
-
- case 3:
- new_acl_entry->ace_access = file_acl->o_access << 6;
- idp->id_type = SMB_ACL_OTHER;
- break;
-
- case 1:
- new_acl_entry->ace_access = file_acl->u_access << 6;
- idp->id_type = SMB_ACL_USER_OBJ;
- break;
-
- default:
- return(NULL);
-
- }
-
- acl_entry_link_head->count++;
- DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
- }
-
- acl_entry_link_head->count = 0;
- SAFE_FREE(file_acl);
-
- return(acl_entry_link_head);
+ return aixacl_sys_acl_delete_def_file(handle, path);
}
-SMB_ACL_T sys_acl_get_fd(int fd)
-{
- struct acl *file_acl = (struct acl *)NULL;
- struct acl_entry *acl_entry;
- struct new_acl_entry *new_acl_entry;
- struct ace_id *idp;
- struct acl_entry_link *acl_entry_link;
- struct acl_entry_link *acl_entry_link_head;
- int i;
- int rc = 0;
- uid_t user_id;
-
- /* Get the acl using fstatacl */
-
- DEBUG(10,("Entering sys_acl_get_fd\n"));
- DEBUG(10,("fd is %d\n",fd));
- file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
-
- if(file_acl == NULL) {
- errno=ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- return(NULL);
- }
-
- memset(file_acl,0,BUFSIZ);
-
- rc = fstatacl(fd,0,file_acl,BUFSIZ);
- if(rc == -1) {
- DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- DEBUG(10,("Got facl and returned it\n"));
-
- /* Point to the first acl entry in the acl */
-
- acl_entry = file_acl->acl_ext;
- /* Begin setting up the head of the linked list *
- * that will be used for the storing the acl *
- * in a way that is useful for the posix_acls.c *
- * code. */
-
- acl_entry_link_head = acl_entry_link = sys_acl_init(0);
- if(acl_entry_link_head == NULL){
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
-
- if(acl_entry_link->entryp == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- DEBUG(10,("acl_entry is %d\n",acl_entry));
- DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
-
- /* Check if the extended acl bit is on. *
- * If it isn't, do not show the *
- * contents of the acl since AIX intends *
- * the extended info to remain unused */
-
- if(file_acl->acl_mode & S_IXACL){
- /* while we are not pointing to the very end */
- while(acl_entry < acl_last(file_acl)) {
- /* before we malloc anything, make sure this is */
- /* a valid acl entry and one that we want to map */
-
- idp = id_nxt(acl_entry->ace_id);
- if((acl_entry->ace_type == ACC_SPECIFY ||
- (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
- acl_entry = acl_nxt(acl_entry);
- continue;
- }
-
- idp = acl_entry->ace_id;
-
- /* Check if this is the first entry in the linked list. *
- * The first entry needs to keep prevp pointing to NULL *
- * and already has entryp allocated. */
-
- if(acl_entry_link_head->count != 0) {
- acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
- if(acl_entry_link->nextp == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
- acl_entry_link->nextp->prevp = acl_entry_link;
- acl_entry_link = acl_entry_link->nextp;
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
- if(acl_entry_link->entryp == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- acl_entry_link->nextp = NULL;
- }
-
- acl_entry_link->entryp->ace_len = acl_entry->ace_len;
-
- /* Don't really need this since all types are going *
- * to be specified but, it's better than leaving it 0 */
-
- acl_entry_link->entryp->ace_type = acl_entry->ace_type;
- acl_entry_link->entryp->ace_access = acl_entry->ace_access;
-
- memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
-
- /* The access in the acl entries must be left shifted by *
- * three bites, because they will ultimately be compared *
- * to S_IRUSR, S_IWUSR, and S_IXUSR. */
-
- switch(acl_entry->ace_type){
- case ACC_PERMIT:
- case ACC_SPECIFY:
- acl_entry_link->entryp->ace_access = acl_entry->ace_access;
- acl_entry_link->entryp->ace_access <<= 6;
- acl_entry_link_head->count++;
- break;
- case ACC_DENY:
- /* Since there is no way to return a DENY acl entry *
- * change to PERMIT and then shift. */
- DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
- acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
- DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
- acl_entry_link->entryp->ace_access <<= 6;
- acl_entry_link_head->count++;
- break;
- default:
- return(0);
- }
-
- DEBUG(10,("acl_entry = %d\n",acl_entry));
- DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
-
- acl_entry = acl_nxt(acl_entry);
- }
- } /* end of if enabled */
-
- /* Since owner, group, other acl entries are not *
- * part of the acl entries in an acl, they must *
- * be dummied up to become part of the list. */
-
- for( i = 1; i < 4; i++) {
- DEBUG(10,("i is %d\n",i));
- if(acl_entry_link_head->count != 0){
- acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
- if(acl_entry_link->nextp == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- SAFE_FREE(file_acl);
- return(NULL);
- }
-
- acl_entry_link->nextp->prevp = acl_entry_link;
- acl_entry_link = acl_entry_link->nextp;
- acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
-
- if(acl_entry_link->entryp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
- return(NULL);
- }
- }
-
- acl_entry_link->nextp = NULL;
-
- new_acl_entry = acl_entry_link->entryp;
- idp = new_acl_entry->ace_id;
-
- new_acl_entry->ace_len = sizeof(struct acl_entry);
- new_acl_entry->ace_type = ACC_PERMIT;
- idp->id_len = sizeof(struct ace_id);
- DEBUG(10,("idp->id_len = %d\n",idp->id_len));
- memset(idp->id_data,0,sizeof(uid_t));
-
- switch(i) {
- case 2:
- new_acl_entry->ace_access = file_acl->g_access << 6;
- idp->id_type = SMB_ACL_GROUP_OBJ;
- break;
-
- case 3:
- new_acl_entry->ace_access = file_acl->o_access << 6;
- idp->id_type = SMB_ACL_OTHER;
- break;
-
- case 1:
- new_acl_entry->ace_access = file_acl->u_access << 6;
- idp->id_type = SMB_ACL_USER_OBJ;
- break;
-
- default:
- return(NULL);
- }
-
- acl_entry_link_head->count++;
- DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
- }
-
- acl_entry_link_head->count = 0;
- SAFE_FREE(file_acl);
+#elif defined(HAVE_TRU64_ACLS)
- return(acl_entry_link_head);
-}
-
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- *permset = *permset & ~0777;
- return(0);
+ return tru64acl_sys_acl_get_file(handle, path_p, type);
}
-int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- if((perm != 0) &&
- (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
- return(-1);
-
- *permset |= perm;
- DEBUG(10,("This is the permset now: %d\n",*permset));
- return(0);
+ return tru64acl_sys_acl_get_fd(handle, fsp, fd);
}
-char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- return(NULL);
+ return tru64acl_sys_acl_set_file(handle, name, type, acl_d);
}
-SMB_ACL_T sys_acl_init( int count)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- struct acl_entry_link *theacl = NULL;
-
- DEBUG(10,("Entering sys_acl_init\n"));
-
- theacl = SMB_MALLOC_P(struct acl_entry_link);
- if(theacl == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_init is %d\n",errno));
- return(NULL);
- }
-
- theacl->count = 0;
- theacl->nextp = NULL;
- theacl->prevp = NULL;
- theacl->entryp = NULL;
- DEBUG(10,("Exiting sys_acl_init\n"));
- return(theacl);
+ return tru64acl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- struct acl_entry_link *theacl;
- struct acl_entry_link *acl_entryp;
- struct acl_entry_link *temp_entry;
- int counting;
-
- DEBUG(10,("Entering the sys_acl_create_entry\n"));
-
- theacl = acl_entryp = *pacl;
-
- /* Get to the end of the acl before adding entry */
-
- for(counting=0; counting < theacl->count; counting++){
- DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
- temp_entry = acl_entryp;
- acl_entryp = acl_entryp->nextp;
- }
-
- if(theacl->count != 0){
- temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
- if(acl_entryp == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
- return(-1);
- }
-
- DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
- acl_entryp->prevp = temp_entry;
- DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
- }
-
- *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
- if(*pentry == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
- return(-1);
- }
-
- memset(*pentry,0,sizeof(struct new_acl_entry));
- acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
- acl_entryp->entryp->ace_type = ACC_PERMIT;
- acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
- acl_entryp->nextp = NULL;
- theacl->count++;
- DEBUG(10,("Exiting sys_acl_create_entry\n"));
- return(0);
+ return tru64acl_sys_acl_delete_def_file(handle, path);
}
-int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
- DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
- entry->ace_id->id_type = tagtype;
- DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
- DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
-}
+#elif defined(HAVE_SOLARIS_ACLS) || defined(HAVE_UNIXWARE_ACLS)
-int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
- memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
- DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
- return(0);
+ return solarisacl_sys_acl_get_file(handle, path_p, type);
}
-int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
- if(!(*permset & S_IXUSR) &&
- !(*permset & S_IWUSR) &&
- !(*permset & S_IRUSR) &&
- (*permset != 0))
- return(-1);
-
- entry->ace_access = *permset;
- DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
- DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
- return(0);
+ return solarisacl_sys_acl_get_fd(handle, fsp, fd);
}
-int sys_acl_valid( SMB_ACL_T theacl )
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- int user_obj = 0;
- int group_obj = 0;
- int other_obj = 0;
- struct acl_entry_link *acl_entry;
-
- for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
- user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
- group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
- other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
- }
-
- DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
-
- if(user_obj != 1 || group_obj != 1 || other_obj != 1)
- return(-1);
-
- return(0);
+ return solarisacl_sys_acl_set_file(handle, name, type, acl_d);
}
-int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- struct acl_entry_link *acl_entry_link = NULL;
- struct acl *file_acl = NULL;
- struct acl *file_acl_temp = NULL;
- struct acl_entry *acl_entry = NULL;
- struct ace_id *ace_id = NULL;
- uint id_type;
- uint ace_access;
- uint user_id;
- uint acl_length;
- uint rc;
-
- DEBUG(10,("Entering sys_acl_set_file\n"));
- DEBUG(10,("File name is %s\n",name));
-
- /* AIX has no default ACL */
- if(acltype == SMB_ACL_TYPE_DEFAULT)
- return(0);
-
- acl_length = BUFSIZ;
- file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
-
- if(file_acl == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
- return(-1);
- }
-
- memset(file_acl,0,BUFSIZ);
-
- file_acl->acl_len = ACL_SIZ;
- file_acl->acl_mode = S_IXACL;
-
- for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
- acl_entry_link->entryp->ace_access >>= 6;
- id_type = acl_entry_link->entryp->ace_id->id_type;
-
- switch(id_type) {
- case SMB_ACL_USER_OBJ:
- file_acl->u_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_GROUP_OBJ:
- file_acl->g_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_OTHER:
- file_acl->o_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_MASK:
- continue;
- }
-
- if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
- acl_length += sizeof(struct acl_entry);
- file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
- if(file_acl_temp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
- return(-1);
- }
-
- memcpy(file_acl_temp,file_acl,file_acl->acl_len);
- SAFE_FREE(file_acl);
- file_acl = file_acl_temp;
- }
-
- acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
- file_acl->acl_len += sizeof(struct acl_entry);
- acl_entry->ace_len = acl_entry_link->entryp->ace_len;
- acl_entry->ace_access = acl_entry_link->entryp->ace_access;
-
- /* In order to use this, we'll need to wait until we can get denies */
- /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
- acl_entry->ace_type = ACC_SPECIFY; */
-
- acl_entry->ace_type = ACC_SPECIFY;
-
- ace_id = acl_entry->ace_id;
-
- ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
- DEBUG(10,("The id type is %d\n",ace_id->id_type));
- ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
- memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
- memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
- }
-
- rc = chacl(name,file_acl,file_acl->acl_len);
- DEBUG(10,("errno is %d\n",errno));
- DEBUG(10,("return code is %d\n",rc));
- SAFE_FREE(file_acl);
- DEBUG(10,("Exiting the sys_acl_set_file\n"));
- return(rc);
-}
-
-int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
-{
- struct acl_entry_link *acl_entry_link = NULL;
- struct acl *file_acl = NULL;
- struct acl *file_acl_temp = NULL;
- struct acl_entry *acl_entry = NULL;
- struct ace_id *ace_id = NULL;
- uint id_type;
- uint user_id;
- uint acl_length;
- uint rc;
-
- DEBUG(10,("Entering sys_acl_set_fd\n"));
- acl_length = BUFSIZ;
- file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
-
- if(file_acl == NULL) {
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
- return(-1);
- }
-
- memset(file_acl,0,BUFSIZ);
-
- file_acl->acl_len = ACL_SIZ;
- file_acl->acl_mode = S_IXACL;
-
- for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
- acl_entry_link->entryp->ace_access >>= 6;
- id_type = acl_entry_link->entryp->ace_id->id_type;
- DEBUG(10,("The id_type is %d\n",id_type));
-
- switch(id_type) {
- case SMB_ACL_USER_OBJ:
- file_acl->u_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_GROUP_OBJ:
- file_acl->g_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_OTHER:
- file_acl->o_access = acl_entry_link->entryp->ace_access;
- continue;
- case SMB_ACL_MASK:
- continue;
- }
-
- if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
- acl_length += sizeof(struct acl_entry);
- file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
- if(file_acl_temp == NULL) {
- SAFE_FREE(file_acl);
- errno = ENOMEM;
- DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
- return(-1);
- }
-
- memcpy(file_acl_temp,file_acl,file_acl->acl_len);
- SAFE_FREE(file_acl);
- file_acl = file_acl_temp;
- }
-
- acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
- file_acl->acl_len += sizeof(struct acl_entry);
- acl_entry->ace_len = acl_entry_link->entryp->ace_len;
- acl_entry->ace_access = acl_entry_link->entryp->ace_access;
-
- /* In order to use this, we'll need to wait until we can get denies */
- /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
- acl_entry->ace_type = ACC_SPECIFY; */
-
- acl_entry->ace_type = ACC_SPECIFY;
-
- ace_id = acl_entry->ace_id;
-
- ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
- DEBUG(10,("The id type is %d\n",ace_id->id_type));
- ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
- memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
- memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
- }
-
- rc = fchacl(fd,file_acl,file_acl->acl_len);
- DEBUG(10,("errno is %d\n",errno));
- DEBUG(10,("return code is %d\n",rc));
- SAFE_FREE(file_acl);
- DEBUG(10,("Exiting sys_acl_set_fd\n"));
- return(rc);
+ return solarisacl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-int sys_acl_delete_def_file(const char *name)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- /* AIX has no default ACL */
- return 0;
+ return solarisacl_sys_acl_delete_def_file(handle, path);
}
-int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- return(*permset & perm);
-}
+#elif defined(HAVE_HPUX_ACLS)
-int sys_acl_free_text(char *text)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- return(0);
+ return hpuxacl_sys_acl_get_file(handle, path_p, type);
}
-int sys_acl_free_acl(SMB_ACL_T posix_acl)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- struct acl_entry_link *acl_entry_link;
-
- for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
- SAFE_FREE(acl_entry_link->prevp->entryp);
- SAFE_FREE(acl_entry_link->prevp);
- }
-
- SAFE_FREE(acl_entry_link->prevp->entryp);
- SAFE_FREE(acl_entry_link->prevp);
- SAFE_FREE(acl_entry_link->entryp);
- SAFE_FREE(acl_entry_link);
-
- return(0);
+ return hpuxacl_sys_acl_get_fd(handle, fsp, fd);
}
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- return(0);
+ return hpuxacl_sys_acl_set_file(handle, name, type, acl_d);
}
-#else /* No ACLs. */
-
-int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- errno = ENOSYS;
- return -1;
+ return hpuxacl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- errno = ENOSYS;
- return -1;
+ return hpuxacl_sys_acl_delete_def_file(handle, path);
}
-int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- errno = ENOSYS;
- return -1;
-}
+#elif defined(HAVE_IRIX_ACLS)
-void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
- errno = ENOSYS;
- return NULL;
+ return irixacl_sys_acl_get_file(handle, path_p, type);
}
-SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
- errno = ENOSYS;
- return (SMB_ACL_T)NULL;
+ return irixacl_sys_acl_get_fd(handle, fsp, fd);
}
-SMB_ACL_T sys_acl_get_fd(int fd)
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
- errno = ENOSYS;
- return (SMB_ACL_T)NULL;
+ return irixacl_sys_acl_set_file(handle, name, type, acl_d);
}
-int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
- errno = ENOSYS;
- return -1;
+ return irixacl_sys_acl_set_fd(handle, fsp, fd, acl_d);
}
-int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
- errno = ENOSYS;
- return -1;
+ return irixacl_sys_acl_delete_def_file(handle, path);
}
-int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- errno = ENOSYS;
- return (permset & perm) ? 1 : 0;
-}
+#else /* No ACLs. */
-char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
+SMB_ACL_T sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p, SMB_ACL_TYPE_T type)
{
+#ifdef ENOTSUP
+ errno = ENOTSUP;
+#else
errno = ENOSYS;
+#endif
return NULL;
}
-int sys_acl_free_text(char *text)
-{
- errno = ENOSYS;
- return -1;
-}
-
-SMB_ACL_T sys_acl_init( int count)
+SMB_ACL_T sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
+#ifdef ENOTSUP
+ errno = ENOTSUP;
+#else
errno = ENOSYS;
+#endif
return NULL;
}
-int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_valid( SMB_ACL_T theacl )
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int sys_acl_delete_def_file(const char *name)
+int sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
{
+#ifdef ENOTSUP
+ errno = ENOTSUP;
+#else
errno = ENOSYS;
+#endif
return -1;
}
-int sys_acl_free_acl(SMB_ACL_T the_acl)
+int sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, SMB_ACL_T acl_d)
{
+#ifdef ENOTSUP
+ errno = ENOTSUP;
+#else
errno = ENOSYS;
+#endif
return -1;
}
-int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
+int sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
{
+#ifdef ENOTSUP
+ errno = ENOTSUP;
+#else
errno = ENOSYS;
+#endif
return -1;
}
-#endif /* No ACLs. */
+#endif
/************************************************************************
Deliberately outside the ACL defines. Return 1 if this is a "no acls"
diff --git a/source/lib/sysquotas_linux.c b/source/lib/sysquotas_linux.c
index 761562b402e..9c0d0056f6d 100644
--- a/source/lib/sysquotas_linux.c
+++ b/source/lib/sysquotas_linux.c
@@ -526,9 +526,9 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
case SMB_USER_FS_QUOTA_TYPE:
id.uid = getuid();
- if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
- if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
- ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
+ ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
}
}
@@ -541,9 +541,9 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
case SMB_GROUP_FS_QUOTA_TYPE:
id.gid = getgid();
- if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
- if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
- ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
+ ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
}
}
diff --git a/source/lib/system.c b/source/lib/system.c
index 2e5f42307bd..20b31113ecd 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -44,6 +44,27 @@
/*******************************************************************
+ A wrapper for memalign
+********************************************************************/
+
+void* sys_memalign( size_t align, size_t size )
+{
+#if defined(HAVE_MEMALIGN)
+ return memalign( align, size );
+#elif defined(HAVE_POSIX_MEMALIGN)
+ char *p = NULL;
+ int ret = posix_memalign( &p, align, size );
+ if ( ret == 0 )
+ return p;
+
+ return NULL;
+#else
+ DEBUG(0,("memalign functionalaity not available on this platform!\n"));
+ return NULL;
+#endif
+}
+
+/*******************************************************************
A wrapper for usleep in case we don't have one.
********************************************************************/
@@ -105,7 +126,6 @@ ssize_t sys_write(int fd, const void *buf, size_t count)
return ret;
}
-
/*******************************************************************
A pread wrapper that will deal with EINTR and 64-bit file offsets.
********************************************************************/
@@ -175,6 +195,20 @@ ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct
}
/*******************************************************************
+A recv wrapper that will deal with EINTR.
+********************************************************************/
+
+ssize_t sys_recv(int fd, void *buf, size_t count, int flags)
+{
+ ssize_t ret;
+
+ do {
+ ret = recv(fd, buf, count, flags);
+ } while (ret == -1 && errno == EINTR);
+ return ret;
+}
+
+/*******************************************************************
A recvfrom wrapper that will deal with EINTR.
********************************************************************/
@@ -366,6 +400,31 @@ FILE *sys_fopen(const char *path, const char *type)
#endif
}
+
+/*******************************************************************
+ A flock() wrapper that will perform the kernel flock.
+********************************************************************/
+
+void kernel_flock(int fd, uint32 share_mode)
+{
+#if HAVE_KERNEL_SHARE_MODES
+ int kernel_mode = 0;
+ if (share_mode == FILE_SHARE_WRITE) {
+ kernel_mode = LOCK_MAND|LOCK_WRITE;
+ } else if (share_mode == FILE_SHARE_READ) {
+ kernel_mode = LOCK_MAND|LOCK_READ;
+ } else if (share_mode == FILE_SHARE_NONE) {
+ kernel_mode = LOCK_MAND;
+ }
+ if (kernel_mode) {
+ flock(fd, kernel_mode);
+ }
+#endif
+ ;
+}
+
+
+
/*******************************************************************
An opendir wrapper that will deal with 64 bit filesizes.
********************************************************************/
@@ -922,6 +981,82 @@ void sys_endpwent(void)
Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
****************************************************************************/
+#ifdef ENABLE_BUILD_FARM_HACKS
+
+/*
+ * In the build farm we want to be able to join machines to the domain. As we
+ * don't have root access, we need to bypass direct access to /etc/passwd
+ * after a user has been created via samr. Fake those users.
+ */
+
+static struct passwd *fake_pwd;
+static int num_fake_pwd;
+
+struct passwd *sys_getpwnam(const char *name)
+{
+ int i;
+
+ for (i=0; i<num_fake_pwd; i++) {
+ if (strcmp(fake_pwd[i].pw_name, name) == 0) {
+ DEBUG(10, ("Returning fake user %s\n", name));
+ return &fake_pwd[i];
+ }
+ }
+
+ return getpwnam(name);
+}
+
+struct passwd *sys_getpwuid(uid_t uid)
+{
+ int i;
+
+ for (i=0; i<num_fake_pwd; i++) {
+ if (fake_pwd[i].pw_uid == uid) {
+ DEBUG(10, ("Returning fake user %s\n",
+ fake_pwd[i].pw_name));
+ return &fake_pwd[i];
+ }
+ }
+
+ return getpwuid(uid);
+}
+
+void faked_create_user(const char *name)
+{
+ int i;
+ uid_t uid;
+ struct passwd new_pwd;
+
+ for (i=0; i<10; i++) {
+ generate_random_buffer((unsigned char *)&uid,
+ sizeof(uid));
+ if (getpwuid(uid) == NULL) {
+ break;
+ }
+ }
+
+ if (i==10) {
+ /* Weird. No free uid found... */
+ return;
+ }
+
+ new_pwd.pw_name = SMB_STRDUP(name);
+ new_pwd.pw_passwd = SMB_STRDUP("x");
+ new_pwd.pw_uid = uid;
+ new_pwd.pw_gid = 100;
+ new_pwd.pw_gecos = SMB_STRDUP("faked user");
+ new_pwd.pw_dir = SMB_STRDUP("/nodir");
+ new_pwd.pw_shell = SMB_STRDUP("/bin/false");
+
+ ADD_TO_ARRAY(NULL, struct passwd, new_pwd, &fake_pwd,
+ &num_fake_pwd);
+
+ DEBUG(10, ("Added fake user %s, have %d fake users\n",
+ name, num_fake_pwd));
+}
+
+#else
+
struct passwd *sys_getpwnam(const char *name)
{
return getpwnam(name);
@@ -932,6 +1067,8 @@ struct passwd *sys_getpwuid(uid_t uid)
return getpwuid(uid);
}
+#endif
+
struct group *sys_getgrnam(const char *name)
{
return getgrnam(name);
@@ -1417,7 +1554,12 @@ int sys_dup2(int oldfd, int newfd)
ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
{
#if defined(HAVE_GETXATTR)
+#ifndef XATTR_ADD_OPT
return getxattr(path, name, value, size);
+#else
+ int options = 0;
+ return getxattr(path, name, value, size, 0, options);
+#endif
#elif defined(HAVE_GETEA)
return getea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FILE)
@@ -1462,6 +1604,9 @@ 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_GETXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return getxattr(path, name, value, size, 0, options);
#elif defined(HAVE_LGETEA)
return lgetea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_LINK)
@@ -1501,7 +1646,12 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
{
#if defined(HAVE_FGETXATTR)
+#ifndef XATTR_ADD_OPT
return fgetxattr(filedes, name, value, size);
+#else
+ int options = 0;
+ return fgetxattr(filedes, name, value, size, 0, options);
+#endif
#elif defined(HAVE_FGETEA)
return fgetea(filedes, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FD)
@@ -1702,7 +1852,12 @@ static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t
ssize_t sys_listxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LISTXATTR)
+#ifndef XATTR_ADD_OPT
return listxattr(path, list, size);
+#else
+ int options = 0;
+ return listxattr(path, list, size, options);
+#endif
#elif defined(HAVE_LISTEA)
return listea(path, list, size);
#elif defined(HAVE_EXTATTR_LIST_FILE)
@@ -1721,6 +1876,9 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LLISTXATTR)
return llistxattr(path, list, size);
+#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return listxattr(path, list, size, options);
#elif defined(HAVE_LLISTEA)
return llistea(path, list, size);
#elif defined(HAVE_EXTATTR_LIST_LINK)
@@ -1738,7 +1896,12 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
ssize_t sys_flistxattr (int filedes, char *list, size_t size)
{
#if defined(HAVE_FLISTXATTR)
+#ifndef XATTR_ADD_OPT
return flistxattr(filedes, list, size);
+#else
+ int options = 0;
+ return flistxattr(filedes, list, size, options);
+#endif
#elif defined(HAVE_FLISTEA)
return flistea(filedes, list, size);
#elif defined(HAVE_EXTATTR_LIST_FD)
@@ -1756,7 +1919,12 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size)
int sys_removexattr (const char *path, const char *name)
{
#if defined(HAVE_REMOVEXATTR)
+#ifndef XATTR_ADD_OPT
return removexattr(path, name);
+#else
+ int options = 0;
+ return removexattr(path, name, options);
+#endif
#elif defined(HAVE_REMOVEEA)
return removeea(path, name);
#elif defined(HAVE_EXTATTR_DELETE_FILE)
@@ -1783,6 +1951,9 @@ int sys_lremovexattr (const char *path, const char *name)
{
#if defined(HAVE_LREMOVEXATTR)
return lremovexattr(path, name);
+#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return removexattr(path, name, options);
#elif defined(HAVE_LREMOVEEA)
return lremoveea(path, name);
#elif defined(HAVE_EXTATTR_DELETE_LINK)
@@ -1808,7 +1979,12 @@ int sys_lremovexattr (const char *path, const char *name)
int sys_fremovexattr (int filedes, const char *name)
{
#if defined(HAVE_FREMOVEXATTR)
+#ifndef XATTR_ADD_OPT
return fremovexattr(filedes, name);
+#else
+ int options = 0;
+ return fremovexattr(filedes, name, options);
+#endif
#elif defined(HAVE_FREMOVEEA)
return fremoveea(filedes, name);
#elif defined(HAVE_EXTATTR_DELETE_FD)
@@ -1839,7 +2015,12 @@ int sys_fremovexattr (int filedes, const char *name)
int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
{
#if defined(HAVE_SETXATTR)
+#ifndef XATTR_ADD_OPT
return setxattr(path, name, value, size, flags);
+#else
+ int options = 0;
+ return setxattr(path, name, value, size, 0, options);
+#endif
#elif defined(HAVE_SETEA)
return setea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FILE)
@@ -1888,6 +2069,9 @@ 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_SETXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return setxattr(path, name, value, size, 0, options);
#elif defined(LSETEA)
return lsetea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_LINK)
@@ -1936,7 +2120,12 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
{
#if defined(HAVE_FSETXATTR)
+#ifndef XATTR_ADD_OPT
return fsetxattr(filedes, name, value, size, flags);
+#else
+ int options = 0;
+ return fsetxattr(filedes, name, value, size, 0, options);
+#endif
#elif defined(HAVE_FSETEA)
return fsetea(filedes, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FD)
@@ -2164,3 +2353,28 @@ int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct
return -1;
}
#endif /* WITH_AIO */
+
+int sys_getpeereid( int s, uid_t *uid)
+{
+#if defined(HAVE_PEERCRED)
+ struct ucred cred;
+ socklen_t cred_len = sizeof(struct ucred);
+ int ret;
+
+ ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
+ if (ret != 0) {
+ return -1;
+ }
+
+ if (cred_len != sizeof(struct ucred)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *uid = cred.uid;
+ return 0;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
diff --git a/source/lib/system_smbd.c b/source/lib/system_smbd.c
index fc506c901db..509b2bbcb1e 100644
--- a/source/lib/system_smbd.c
+++ b/source/lib/system_smbd.c
@@ -181,11 +181,18 @@ BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
groups = NULL;
/* Add in primary group first */
- add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp);
+ if (!add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp)) {
+ SAFE_FREE(temp_groups);
+ return False;
+ }
- for (i=0; i<max_grp; i++)
- add_gid_to_array_unique(mem_ctx, temp_groups[i],
- &groups, &ngrp);
+ for (i=0; i<max_grp; i++) {
+ if (!add_gid_to_array_unique(mem_ctx, temp_groups[i],
+ &groups, &ngrp)) {
+ SAFE_FREE(temp_groups);
+ return False;
+ }
+ }
*p_ngroups = ngrp;
*ret_groups = groups;
diff --git a/source/lib/talloc/Makefile.in b/source/lib/talloc/Makefile.in
new file mode 100644
index 00000000000..14e81156921
--- /dev/null
+++ b/source/lib/talloc/Makefile.in
@@ -0,0 +1,71 @@
+#!gmake
+#
+prefix = @prefix@
+datarootdir = @datarootdir@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+mandir = @mandir@
+VPATH = @srcdir@:@libreplacedir@
+srcdir = @srcdir@
+builddir = @builddir@
+XSLTPROC = @XSLTPROC@
+INSTALLCMD = @INSTALL@
+CC = @CC@
+CFLAGS = @CFLAGS@ -DHAVE_CONFIG_H= -I. -I@srcdir@ -I@libreplacedir@
+EXTRA_TARGETS = @DOC_TARGET@
+
+.SUFFIXES: .c .o .3 .3.xml .xml .html
+
+LIBOBJ = @TALLOCOBJ@ @LIBREPLACEOBJ@
+
+all: showflags libtalloc.a testsuite $(EXTRA_TARGETS)
+
+showflags:
+ @echo 'talloc will be compiled with flags:'
+ @echo ' CFLAGS = $(CFLAGS)'
+ @echo ' LIBS = $(LIBS)'
+
+testsuite: $(LIBOBJ) testsuite.o
+ $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS)
+
+libtalloc.a: $(LIBOBJ)
+ ar -rv $@ $(LIBOBJ)
+ @-ranlib $@
+
+install: all
+ ${INSTALLCMD} -d ${libdir}
+ ${INSTALLCMD} -m 755 libtalloc.a $(libdir)
+ ${INSTALLCMD} -d ${includedir}
+ ${INSTALLCMD} -m 644 $(srcdir)/talloc.h $(includedir)
+ ${INSTALLCMD} -m 644 talloc.pc $(libdir)/pkgconfig
+ if [ -f talloc.3 ];then ${INSTALLCMD} -d ${mandir}/man3; fi
+ if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(mandir)/man3; fi
+
+doc: talloc.3 talloc.3.html
+
+.3.xml.3:
+ -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+
+.xml.html:
+ -test -z "$(XSLTPROC)" || $(XSLTPROC) --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $<
+
+clean:
+ rm -f *~ $(LIBOBJ) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html
+
+test: testsuite
+ ./testsuite
+
+gcov:
+ gcov talloc.c
+
+installcheck:
+ $(MAKE) test
+
+distclean: clean
+ rm -f *~ */*~
+ rm -f Makefile
+ rm -f config.log config.status config.h config.cache
+
+realdistclean: distclean
+ rm -f configure config.h.in
diff --git a/source/lib/talloc/aclocal.m4 b/source/lib/talloc/aclocal.m4
new file mode 100644
index 00000000000..5605e476bab
--- /dev/null
+++ b/source/lib/talloc/aclocal.m4
@@ -0,0 +1 @@
+m4_include(libreplace.m4)
diff --git a/source/lib/talloc/autogen.sh b/source/lib/talloc/autogen.sh
new file mode 100755
index 00000000000..bf84eeee19a
--- /dev/null
+++ b/source/lib/talloc/autogen.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f configure config.h.in
+
+IPATHS="-I libreplace -I lib/replace -I ../libreplace -I ../replace"
+autoconf $IPATHS || exit 1
+autoheader $IPATHS || exit 1
+
+rm -rf autom4te.cache
+
+echo "Now run ./configure and then make."
+exit 0
+
diff --git a/source/lib/talloc/config.guess b/source/lib/talloc/config.guess
new file mode 100755
index 00000000000..ad5281e66e9
--- /dev/null
+++ b/source/lib/talloc/config.guess
@@ -0,0 +1,1466 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-08-03'
+
+# This file 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/source/lib/talloc/config.mk b/source/lib/talloc/config.mk
new file mode 100644
index 00000000000..0b06687dabd
--- /dev/null
+++ b/source/lib/talloc/config.mk
@@ -0,0 +1,18 @@
+################################################
+# Start LIBRARY LIBTALLOC
+[LIBRARY::LIBTALLOC]
+VERSION = 0.0.1
+SO_VERSION = 0
+OBJ_FILES = talloc.o
+MANPAGE = talloc.3
+CFLAGS = -Ilib/talloc
+PUBLIC_HEADERS = talloc.h
+DESCRIPTION = A hierarchical pool based memory system with destructors
+#
+# End LIBRARY LIBTALLOC
+################################################
+
+[BINARY::TALLOC]
+OBJ_FILES = testsuite.o
+PRIVATE_DEPENDENCIES = LIBTALLOC
+INSTALLDIR = TORTUREDIR/LOCAL
diff --git a/source/lib/talloc/config.sub b/source/lib/talloc/config.sub
new file mode 100755
index 00000000000..1c366dfde9a
--- /dev/null
+++ b/source/lib/talloc/config.sub
@@ -0,0 +1,1579 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-07-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/source/lib/talloc/configure.ac b/source/lib/talloc/configure.ac
new file mode 100644
index 00000000000..51e7256bf88
--- /dev/null
+++ b/source/lib/talloc/configure.ac
@@ -0,0 +1,18 @@
+AC_PREREQ(2.50)
+AC_INIT(talloc.h)
+AC_CONFIG_SRCDIR([talloc.c])
+AC_SUBST(datarootdir)
+AC_CONFIG_HEADER(config.h)
+
+AC_LIBREPLACE_ALL_CHECKS
+
+m4_include(libtalloc.m4)
+
+AC_PATH_PROG(XSLTPROC,xsltproc)
+DOC_TARGET=""
+if test -n "$XSLTPROC"; then
+ DOC_TARGET=doc
+fi
+AC_SUBST(DOC_TARGET)
+
+AC_OUTPUT(Makefile talloc.pc)
diff --git a/source/lib/talloc/install-sh b/source/lib/talloc/install-sh
new file mode 100755
index 00000000000..58719246f04
--- /dev/null
+++ b/source/lib/talloc/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/source/lib/talloc/libtalloc.m4 b/source/lib/talloc/libtalloc.m4
new file mode 100644
index 00000000000..4a0ee3c8fc5
--- /dev/null
+++ b/source/lib/talloc/libtalloc.m4
@@ -0,0 +1,27 @@
+dnl find the talloc sources. This is meant to work both for
+dnl talloc standalone builds, and builds of packages using talloc
+tallocdir=""
+tallocpaths="$srcdir $srcdir/lib/talloc $srcdir/talloc $srcdir/../talloc"
+for d in $tallocpaths; do
+ if test -f "$d/talloc.c"; then
+ tallocdir="$d"
+ AC_SUBST(tallocdir)
+ break;
+ fi
+done
+if test x"$tallocdir" = "x"; then
+ AC_MSG_ERROR([cannot find talloc source in $tallocpaths])
+fi
+TALLOCOBJ="talloc.o"
+AC_SUBST(TALLOCOBJ)
+
+AC_CHECK_SIZEOF(size_t,cross)
+AC_CHECK_SIZEOF(void *,cross)
+
+if test $ac_cv_sizeof_size_t -lt $ac_cv_sizeof_void_p; then
+ AC_WARN([size_t cannot represent the amount of used memory of a process])
+ AC_WARN([please report this to <samba-technical@samba.org>])
+ AC_WARN([sizeof(size_t) = $ac_cv_sizeof_size_t])
+ AC_WARN([sizeof(void *) = $ac_cv_sizeof_void_p])
+ AC_ERROR([sizeof(size_t) < sizeof(void *)])
+fi
diff --git a/source/lib/talloc/talloc.3.xml b/source/lib/talloc/talloc.3.xml
new file mode 100644
index 00000000000..2400fef2dc5
--- /dev/null
+++ b/source/lib/talloc/talloc.3.xml
@@ -0,0 +1,718 @@
+<?xml version="1.0"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry>
+ <refmeta>
+ <refentrytitle>talloc</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>talloc</refname>
+<refpurpose>hierarchical reference counted memory pool system with destructors</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+<synopsis>#include &lt;talloc/talloc.h&gt;</synopsis>
+ </refsynopsisdiv>
+ <refsect1><title>DESCRIPTION</title>
+ <para>
+ If you are used to talloc from Samba3 then please read this
+ carefully, as talloc has changed a lot.
+ </para>
+ <para>
+ The new talloc is a hierarchical, reference counted memory pool
+ system with destructors. Quite a mouthful really, but not too bad
+ once you get used to it.
+ </para>
+ <para>
+ Perhaps the biggest change from Samba3 is that there is no
+ distinction between a "talloc context" and a "talloc pointer". Any
+ pointer returned from talloc() is itself a valid talloc context.
+ This means you can do this:
+ </para>
+ <programlisting>
+ struct foo *X = talloc(mem_ctx, struct foo);
+ X->name = talloc_strdup(X, "foo");
+ </programlisting>
+ <para>
+ and the pointer <literal role="code">X-&gt;name</literal>
+ would be a "child" of the talloc context <literal
+ role="code">X</literal> which is itself a child of
+ <literal role="code">mem_ctx</literal>. So if you do
+ <literal role="code">talloc_free(mem_ctx)</literal> then
+ it is all destroyed, whereas if you do <literal
+ role="code">talloc_free(X)</literal> then just <literal
+ role="code">X</literal> and <literal
+ role="code">X-&gt;name</literal> are destroyed, and if
+ you do <literal
+ role="code">talloc_free(X-&gt;name)</literal> then just
+ the name element of <literal role="code">X</literal> is
+ destroyed.
+ </para>
+ <para>
+ If you think about this, then what this effectively gives you is an
+ n-ary tree, where you can free any part of the tree with
+ talloc_free().
+ </para>
+ <para>
+ If you find this confusing, then I suggest you run the <literal
+ role="code">testsuite</literal> program to watch talloc
+ in action. You may also like to add your own tests to <literal
+ role="code">testsuite.c</literal> to clarify how some
+ particular situation is handled.
+ </para>
+ </refsect1>
+ <refsect1><title>TALLOC API</title>
+ <para>
+ The following is a complete guide to the talloc API. Read it all at
+ least twice.
+ </para>
+ <refsect2><title>(type *)talloc(const void *ctx, type);</title>
+ <para>
+ The talloc() macro is the core of the talloc library. It takes a
+ memory <emphasis role="italic">ctx</emphasis> and a <emphasis
+ role="italic">type</emphasis>, and returns a pointer to a new
+ area of memory of the given <emphasis
+ role="italic">type</emphasis>.
+ </para>
+ <para>
+ The returned pointer is itself a talloc context, so you can use
+ it as the <emphasis role="italic">ctx</emphasis> argument to more
+ calls to talloc() if you wish.
+ </para>
+ <para>
+ The returned pointer is a "child" of the supplied context. This
+ means that if you talloc_free() the <emphasis
+ role="italic">ctx</emphasis> then the new child disappears as
+ well. Alternatively you can free just the child.
+ </para>
+ <para>
+ The <emphasis role="italic">ctx</emphasis> argument to talloc()
+ can be NULL, in which case a new top level context is created.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_size(const void *ctx, size_t size);</title>
+ <para>
+ The function talloc_size() should be used when you don't have a
+ convenient type to pass to talloc(). Unlike talloc(), it is not
+ type safe (as it returns a void *), so you are on your own for
+ type checking.
+ </para>
+ </refsect2>
+ <refsect2><title>(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);</title>
+ <para>
+ The talloc_ptrtype() macro should be used when you have a pointer and
+ want to allocate memory to point at with this pointer. When compiling
+ with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+ and talloc_get_name() will return the current location in the source file.
+ and not the type.
+ </para>
+ </refsect2>
+ <refsect2><title>int talloc_free(void *ptr);</title>
+ <para>
+ The talloc_free() function frees a piece of talloc memory, and
+ all its children. You can call talloc_free() on any pointer
+ returned by talloc().
+ </para>
+ <para>
+ The return value of talloc_free() indicates success or failure,
+ with 0 returned for success and -1 for failure. The only
+ possible failure condition is if <emphasis
+ role="italic">ptr</emphasis> had a destructor attached to it and
+ the destructor returned -1. See <link
+ linkend="talloc_set_destructor"><quote>talloc_set_destructor()</quote></link>
+ for details on destructors.
+ </para>
+ <para>
+ If this pointer has an additional parent when talloc_free() is
+ called then the memory is not actually released, but instead the
+ most recently established parent is destroyed. See <link
+ linkend="talloc_reference"><quote>talloc_reference()</quote></link>
+ for details on establishing additional parents.
+ </para>
+ <para>
+ For more control on which parent is removed, see <link
+ linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>.
+ </para>
+ <para>
+ talloc_free() operates recursively on its children.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_reference"><title>void *talloc_reference(const void *ctx, const void *ptr);</title>
+ <para>
+ The talloc_reference() function makes <emphasis
+ role="italic">ctx</emphasis> an additional parent of <emphasis
+ role="italic">ptr</emphasis>.
+ </para>
+ <para>
+ The return value of talloc_reference() is always the original
+ pointer <emphasis role="italic">ptr</emphasis>, unless talloc ran
+ out of memory in creating the reference in which case it will
+ return NULL (each additional reference consumes around 48 bytes
+ of memory on intel x86 platforms).
+ </para>
+ <para>
+ If <emphasis role="italic">ptr</emphasis> is NULL, then the
+ function is a no-op, and simply returns NULL.
+ </para>
+ <para>
+ After creating a reference you can free it in one of the
+ following ways:
+ </para>
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ you can talloc_free() any parent of the original pointer.
+ That will reduce the number of parents of this pointer by 1,
+ and will cause this pointer to be freed if it runs out of
+ parents.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can talloc_free() the pointer itself. That will destroy
+ the most recently established parent to the pointer and leave
+ the pointer as a child of its current parent.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ For more control on which parent to remove, see <link
+ linkend="talloc_unlink"><quote>talloc_unlink()</quote></link>.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_unlink"><title>int talloc_unlink(const void *ctx, const void *ptr);</title>
+ <para>
+ The talloc_unlink() function removes a specific parent from
+ <emphasis role="italic">ptr</emphasis>. The <emphasis
+ role="italic">ctx</emphasis> passed must either be a context used
+ in talloc_reference() with this pointer, or must be a direct
+ parent of ptr.
+ </para>
+ <para>
+ Note that if the parent has already been removed using
+ talloc_free() then this function will fail and will return -1.
+ Likewise, if <emphasis role="italic">ptr</emphasis> is NULL, then
+ the function will make no modifications and return -1.
+ </para>
+ <para>
+ Usually you can just use talloc_free() instead of
+ talloc_unlink(), but sometimes it is useful to have the
+ additional control on which parent is removed.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_set_destructor"><title>void talloc_set_destructor(const void *ptr, int (*destructor)(void *));</title>
+ <para>
+ The function talloc_set_destructor() sets the <emphasis
+ role="italic">destructor</emphasis> for the pointer <emphasis
+ role="italic">ptr</emphasis>. A <emphasis
+ role="italic">destructor</emphasis> is a function that is called
+ when the memory used by a pointer is about to be released. The
+ destructor receives <emphasis role="italic">ptr</emphasis> as an
+ argument, and should return 0 for success and -1 for failure.
+ </para>
+ <para>
+ The <emphasis role="italic">destructor</emphasis> can do anything
+ it wants to, including freeing other pieces of memory. A common
+ use for destructors is to clean up operating system resources
+ (such as open file descriptors) contained in the structure the
+ destructor is placed on.
+ </para>
+ <para>
+ You can only place one destructor on a pointer. If you need more
+ than one destructor then you can create a zero-length child of
+ the pointer and place an additional destructor on that.
+ </para>
+ <para>
+ To remove a destructor call talloc_set_destructor() with NULL for
+ the destructor.
+ </para>
+ <para>
+ If your destructor attempts to talloc_free() the pointer that it
+ is the destructor for then talloc_free() will return -1 and the
+ free will be ignored. This would be a pointless operation
+ anyway, as the destructor is only called when the memory is just
+ about to go away.
+ </para>
+ </refsect2>
+ <refsect2><title>int talloc_increase_ref_count(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_increase_ref_count(<emphasis
+ role="italic">ptr</emphasis>) function is exactly equivalent to:
+ </para>
+ <programlisting>talloc_reference(NULL, ptr);</programlisting>
+ <para>
+ You can use either syntax, depending on which you think is
+ clearer in your code.
+ </para>
+ <para>
+ It returns 0 on success and -1 on failure.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_reference_count(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ Return the number of references to the pointer.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_set_name"><title>void talloc_set_name(const void *ptr, const char *fmt, ...);</title>
+ <para>
+ Each talloc pointer has a "name". The name is used principally
+ for debugging purposes, although it is also possible to set and
+ get the name on a pointer in as a way of "marking" pointers in
+ your code.
+ </para>
+ <para>
+ The main use for names on pointer is for "talloc reports". See
+ <link
+ linkend="talloc_report"><quote>talloc_report_depth_cb()</quote></link>,
+ <link
+ linkend="talloc_report"><quote>talloc_report_depth_file()</quote></link>,
+ <link
+ linkend="talloc_report"><quote>talloc_report()</quote></link>
+ <link
+ linkend="talloc_report"><quote>talloc_report()</quote></link>
+ and <link
+ linkend="talloc_report_full"><quote>talloc_report_full()</quote></link>
+ for details. Also see <link
+ linkend="talloc_enable_leak_report"><quote>talloc_enable_leak_report()</quote></link>
+ and <link
+ linkend="talloc_enable_leak_report_full"><quote>talloc_enable_leak_report_full()</quote></link>.
+ </para>
+ <para>
+ The talloc_set_name() function allocates memory as a child of the
+ pointer. It is logically equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));</programlisting>
+ <para>
+ Note that multiple calls to talloc_set_name() will allocate more
+ memory without releasing the name. All of the memory is released
+ when the ptr is freed using talloc_free().
+ </para>
+ </refsect2>
+ <refsect2><title>void talloc_set_name_const(const void *<emphasis role="italic">ptr</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title>
+ <para>
+ The function talloc_set_name_const() is just like
+ talloc_set_name(), but it takes a string constant, and is much
+ faster. It is extensively used by the "auto naming" macros, such
+ as talloc_p().
+ </para>
+ <para>
+ This function does not allocate any memory. It just copies the
+ supplied pointer into the internal representation of the talloc
+ ptr. This means you must not pass a <emphasis
+ role="italic">name</emphasis> pointer to memory that will
+ disappear before <emphasis role="italic">ptr</emphasis> is freed
+ with talloc_free().
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_named(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ The talloc_named() function creates a named talloc pointer. It
+ is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+talloc_set_name(ptr, fmt, ....);</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_named_const(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">name</emphasis>);</title>
+ <para>
+ This is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+talloc_set_name_const(ptr, name);</programlisting>
+ </refsect2>
+ <refsect2><title>const char *talloc_get_name(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ This returns the current name for the given talloc pointer,
+ <emphasis role="italic">ptr</emphasis>. See <link
+ linkend="talloc_set_name"><quote>talloc_set_name()</quote></link>
+ for details.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_init(const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ This function creates a zero length named talloc context as a top
+ level context. It is equivalent to:
+ </para>
+ <programlisting>talloc_named(NULL, 0, fmt, ...);</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_new(void *<emphasis role="italic">ctx</emphasis>);</title>
+ <para>
+ This is a utility macro that creates a new memory context hanging
+ off an exiting context, automatically naming it "talloc_new:
+ __location__" where __location__ is the source line it is called
+ from. It is particularly useful for creating a new temporary
+ working context.
+ </para>
+ </refsect2>
+ <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_realloc(const void *<emphasis role="italic">ctx</emphasis>, void *<emphasis role="italic">ptr</emphasis>, <emphasis role="italic">type</emphasis>, <emphasis role="italic">count</emphasis>);</title>
+ <para>
+ The talloc_realloc() macro changes the size of a talloc pointer.
+ It has the following equivalences:
+ </para>
+ <programlisting>talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type);
+talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);</programlisting>
+ <para>
+ The <emphasis role="italic">ctx</emphasis> argument is only used
+ if <emphasis role="italic">ptr</emphasis> is not NULL, otherwise
+ it is ignored.
+ </para>
+ <para>
+ talloc_realloc() returns the new pointer, or NULL on failure.
+ The call will fail either due to a lack of memory, or because the
+ pointer has more than one parent (see <link
+ linkend="talloc_reference"><quote>talloc_reference()</quote></link>).
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_realloc_size(const void *ctx, void *ptr, size_t size);</title>
+ <para>
+ the talloc_realloc_size() function is useful when the type is not
+ known so the type-safe talloc_realloc() cannot be used.
+ </para>
+ </refsect2>
+ <refsect2><title>TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_steal() function changes the parent context of a
+ talloc pointer. It is typically used when the context that the
+ pointer is currently a child of is going to be freed and you wish
+ to keep the memory for a longer time.
+ </para>
+ <para>
+ The talloc_steal() function returns the pointer that you pass it.
+ It does not have any failure modes.
+ </para>
+ <para>
+ NOTE: It is possible to produce loops in the parent/child
+ relationship if you are not careful with talloc_steal(). No
+ guarantees are provided as to your sanity or the safety of your
+ data if you do this.
+ </para>
+ </refsect2>
+ <refsect2><title>TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE **<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_move() function is a wrapper around
+ talloc_steal() which zeros the source pointer after the
+ move. This avoids a potential source of bugs where a
+ programmer leaves a pointer in two structures, and uses the
+ pointer from the old structure after it has been moved to a
+ new one.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_total_size() function returns the total size in bytes
+ used by this pointer and all child pointers. Mostly useful for
+ debugging.
+ </para>
+ <para>
+ Passing NULL is allowed, but it will only give a meaningful
+ result if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() has been called.
+ </para>
+ </refsect2>
+ <refsect2><title>size_t talloc_total_blocks(const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_total_blocks() function returns the total memory block
+ count used by this pointer and all child pointers. Mostly useful
+ for debugging.
+ </para>
+ <para>
+ Passing NULL is allowed, but it will only give a meaningful
+ result if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report"><title>void talloc_report(const void *ptr, FILE *f);</title>
+ <para>
+ The talloc_report() function prints a summary report of all
+ memory used by <emphasis role="italic">ptr</emphasis>. One line
+ of report is printed for each immediate child of ptr, showing the
+ total memory and number of blocks used by that child.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_full"><title>void talloc_report_full(const void *<emphasis role="italic">ptr</emphasis>, FILE *<emphasis role="italic">f</emphasis>);</title>
+ <para>
+ This provides a more detailed report than talloc_report(). It
+ will recursively print the entire tree of memory referenced by
+ the pointer. References in the tree are shown by giving the name
+ of the pointer that is referenced.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_depth_cb">
+ <funcsynopsis><funcprototype>
+ <funcdef>void <function>talloc_report_depth_cb</function></funcdef>
+ <paramdef><parameter>const void *ptr</parameter></paramdef>
+ <paramdef><parameter>int depth</parameter></paramdef>
+ <paramdef><parameter>int max_depth</parameter></paramdef>
+ <paramdef><parameter>void (*callback)(const void *ptr, int depth, int max_depth, int is_ref, void *priv)</parameter></paramdef>
+ <paramdef><parameter>void *priv</parameter></paramdef>
+ </funcprototype></funcsynopsis>
+ <para>
+ This provides a more flexible reports than talloc_report(). It
+ will recursively call the callback for the entire tree of memory
+ referenced by the pointer. References in the tree are passed with
+ <emphasis role="italic">is_ref = 1</emphasis> and the pointer that is referenced.
+ </para>
+ <para>
+ You can pass NULL for the pointer, in which case a report is
+ printed for the top level memory context, but only if
+ talloc_enable_leak_report() or talloc_enable_leak_report_full()
+ has been called.
+ </para>
+ <para>
+ The recursion is stopped when depth >= max_depth.
+ max_depth = -1 means only stop at leaf nodes.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_report_depth_file">
+ <funcsynopsis><funcprototype>
+ <funcdef>void <function>talloc_report_depth_file</function></funcdef>
+ <paramdef><parameter>const void *ptr</parameter></paramdef>
+ <paramdef><parameter>int depth</parameter></paramdef>
+ <paramdef><parameter>int max_depth</parameter></paramdef>
+ <paramdef><parameter>FILE *f</parameter></paramdef>
+ </funcprototype></funcsynopsis>
+ <para>
+ This provides a more flexible reports than talloc_report(). It
+ will let you specify the depth and max_depth.
+ </para>
+ </refsect2>
+ <refsect2 id="talloc_enable_leak_report"><title>void talloc_enable_leak_report(void);</title>
+ <para>
+ This enables calling of talloc_report(NULL, stderr) when the
+ program exits. In Samba4 this is enabled by using the
+ --leak-report command line option.
+ </para>
+ <para>
+ For it to be useful, this function must be called before any
+ other talloc function as it establishes a "null context" that
+ acts as the top of the tree. If you don't call this function
+ first then passing NULL to talloc_report() or
+ talloc_report_full() won't give you the full tree printout.
+ </para>
+ <para>
+ Here is a typical talloc report:
+ </para>
+ <screen format="linespecific">talloc report on 'null_context' (total 267 bytes in 15 blocks)
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+ </screen>
+ </refsect2>
+ <refsect2 id="talloc_enable_leak_report_full"><title>void talloc_enable_leak_report_full(void);</title>
+ <para>
+ This enables calling of talloc_report_full(NULL, stderr) when the
+ program exits. In Samba4 this is enabled by using the
+ --leak-report-full command line option.
+ </para>
+ <para>
+ For it to be useful, this function must be called before any
+ other talloc function as it establishes a "null context" that
+ acts as the top of the tree. If you don't call this function
+ first then passing NULL to talloc_report() or
+ talloc_report_full() won't give you the full tree printout.
+ </para>
+ <para>
+ Here is a typical full report:
+ </para>
+ <screen format="linespecific">full talloc report on 'root' (total 18 bytes in 8 blocks)
+p1 contains 18 bytes in 7 blocks (ref 0)
+ r1 contains 13 bytes in 2 blocks (ref 0)
+ reference to: p2
+ p2 contains 1 bytes in 1 blocks (ref 1)
+ x3 contains 1 bytes in 1 blocks (ref 0)
+ x2 contains 1 bytes in 1 blocks (ref 0)
+ x1 contains 1 bytes in 1 blocks (ref 0)
+ </screen>
+ </refsect2>
+ <refsect2><title>(<emphasis role="italic">type</emphasis> *)talloc_zero(const void *<emphasis role="italic">ctx</emphasis>, <emphasis role="italic">type</emphasis>);</title>
+ <para>
+ The talloc_zero() macro is equivalent to:
+ </para>
+ <programlisting>ptr = talloc(ctx, type);
+if (ptr) memset(ptr, 0, sizeof(type));</programlisting>
+ </refsect2>
+ <refsect2><title>void *talloc_zero_size(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>)</title>
+ <para>
+ The talloc_zero_size() function is useful when you don't have a
+ known type.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_memdup(const void *<emphasis role="italic">ctx</emphasis>, const void *<emphasis role="italic">p</emphasis>, size_t size);</title>
+ <para>
+ The talloc_memdup() function is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, size);
+if (ptr) memcpy(ptr, p, size);</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_strdup(const void *<emphasis role="italic">ctx</emphasis>, const char *<emphasis role="italic">p</emphasis>);</title>
+ <para>
+ The talloc_strdup() function is equivalent to:
+ </para>
+ <programlisting>ptr = talloc_size(ctx, strlen(p)+1);
+if (ptr) memcpy(ptr, p, strlen(p)+1);</programlisting>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_strndup(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">p</emphasis>, size_t <emphasis role="italic">n</emphasis>);</title>
+ <para>
+ The talloc_strndup() function is the talloc equivalent of the C
+ library function strndup(3).
+ </para>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>);</title>
+ <para>
+ The talloc_vasprintf() function is the talloc equivalent of the C
+ library function vasprintf(3).
+ </para>
+ </refsect2>
+ <refsect2><title>char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...);</title>
+ <para>
+ The talloc_asprintf() function is the talloc equivalent of the C
+ library function asprintf(3).
+ </para>
+ <para>
+ This function sets the name of the new pointer to the passed
+ string. This is equivalent to:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, ptr)</programlisting>
+ </refsect2>
+ <refsect2><title>char *talloc_asprintf_append(char *s, const char *fmt, ...);</title>
+ <para>
+ The talloc_asprintf_append() function appends the given formatted
+ string to the given string.
+ </para>
+ </refsect2>
+ <refsect2><title>(type *)talloc_array(const void *ctx, type, uint_t count);</title>
+ <para>
+ The talloc_array() macro is equivalent to:
+ </para>
+ <programlisting>(type *)talloc_size(ctx, sizeof(type) * count);</programlisting>
+ <para>
+ except that it provides integer overflow protection for the
+ multiply, returning NULL if the multiply overflows.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_array_size(const void *ctx, size_t size, uint_t count);</title>
+ <para>
+ The talloc_array_size() function is useful when the type is not
+ known. It operates in the same way as talloc_array(), but takes a
+ size instead of a type.
+ </para>
+ </refsect2>
+ <refsect2><title>(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);</title>
+ <para>
+ The talloc_ptrtype() macro should be used when you have a pointer to an array
+ and want to allocate memory of an array to point at with this pointer. When compiling
+ with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+ and talloc_get_name() will return the current location in the source file.
+ and not the type.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size)</title>
+ <para>
+ This is a non-macro version of talloc_realloc(), which is useful
+ as libraries sometimes want a realloc function pointer. A
+ realloc(3) implementation encapsulates the functionality of
+ malloc(3), free(3) and realloc(3) in one call, which is why it is
+ useful to be able to pass around a single function pointer.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_autofree_context(void);</title>
+ <para>
+ This is a handy utility function that returns a talloc context
+ which will be automatically freed on program exit. This can be
+ used to reduce the noise in memory leak reports.
+ </para>
+ </refsect2>
+ <refsect2><title>void *talloc_check_name(const void *ptr, const char *name);</title>
+ <para>
+ This function checks if a pointer has the specified <emphasis
+ role="italic">name</emphasis>. If it does then the pointer is
+ returned. It it doesn't then NULL is returned.
+ </para>
+ </refsect2>
+ <refsect2><title>(type *)talloc_get_type(const void *ptr, type);</title>
+ <para>
+ This macro allows you to do type checking on talloc pointers. It
+ is particularly useful for void* private pointers. It is
+ equivalent to this:
+ </para>
+ <programlisting>(type *)talloc_check_name(ptr, #type)</programlisting>
+ </refsect2>
+ <refsect2><title>talloc_set_type(const void *ptr, type);</title>
+ <para>
+ This macro allows you to force the name of a pointer to be a
+ particular <emphasis>type</emphasis>. This can be
+ used in conjunction with talloc_get_type() to do type checking on
+ void* pointers.
+ </para>
+ <para>
+ It is equivalent to this:
+ </para>
+ <programlisting>talloc_set_name_const(ptr, #type)</programlisting>
+ </refsect2>
+ </refsect1>
+ <refsect1><title>PERFORMANCE</title>
+ <para>
+ All the additional features of talloc(3) over malloc(3) do come at a
+ price. We have a simple performance test in Samba4 that measures
+ talloc() versus malloc() performance, and it seems that talloc() is
+ about 10% slower than malloc() on my x86 Debian Linux box. For
+ Samba, the great reduction in code complexity that we get by using
+ talloc makes this worthwhile, especially as the total overhead of
+ talloc/malloc in Samba is already quite small.
+ </para>
+ </refsect1>
+ <refsect1><title>SEE ALSO</title>
+ <para>
+ malloc(3), strndup(3), vasprintf(3), asprintf(3),
+ <ulink url="http://talloc.samba.org/"/>
+ </para>
+ </refsect1>
+ <refsect1><title>COPYRIGHT/LICENSE</title>
+ <para>
+ Copyright (C) Andrew Tridgell 2004
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ 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.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/source/lib/talloc.c b/source/lib/talloc/talloc.c
index 51087ef9791..028b44a8c72 100644
--- a/source/lib/talloc.c
+++ b/source/lib/talloc/talloc.c
@@ -1,4 +1,4 @@
-/*
+/*
Samba Unix SMB/CIFS implementation.
Samba trivial allocation library - new interface
@@ -6,11 +6,12 @@
NOTE: Please read talloc_guide.txt for full documentation
Copyright (C) Andrew Tridgell 2004
-
+ Copyright (C) Stefan Metzmacher 2006
+
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -31,8 +32,9 @@
*/
#ifdef _SAMBA_BUILD_
+#include "version.h"
+#if (SAMBA_VERSION_MAJOR<4)
#include "includes.h"
-#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
* we trust ourselves... */
#ifdef malloc
@@ -41,17 +43,14 @@
#ifdef realloc
#undef realloc
#endif
-#endif
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdint.h>
+#define _TALLOC_SAMBA3
+#endif /* (SAMBA_VERSION_MAJOR<4) */
+#endif /* _SAMBA_BUILD_ */
+
+#ifndef _TALLOC_SAMBA3
+#include "replace.h"
#include "talloc.h"
-/* assume a modern system */
-#define HAVE_VA_COPY
-#endif
+#endif /* not _TALLOC_SAMBA3 */
/* use this to force every realloc to change the pointer, to stress test
code that might not cope */
@@ -78,13 +77,23 @@
#endif
#endif
+/* these macros gain us a few percent of speed on gcc */
+#if (__GNUC__ >= 3)
+/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
+ as its first argument */
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
/* this null_context is only used if talloc_enable_leak_report() or
talloc_enable_leak_report_full() is called, otherwise it remains
NULL
*/
-static const void *null_context;
-static void *cleanup_context;
-
+static void *null_context;
+static void *autofree_context;
struct talloc_reference_handle {
struct talloc_reference_handle *next, *prev;
@@ -108,15 +117,16 @@ struct talloc_chunk {
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
/* panic if we get a bad magic value */
-static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
+static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
{
- const char *pp = ptr;
+ const char *pp = (const char *)ptr;
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
- if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
- TALLOC_ABORT("Bad talloc magic value - unknown value");
- }
- if (tc->flags & TALLOC_FLAG_FREE) {
- TALLOC_ABORT("Bad talloc magic value - double free");
+ if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
+ if (tc->flags & TALLOC_FLAG_FREE) {
+ TALLOC_ABORT("Bad talloc magic value - double free");
+ } else {
+ TALLOC_ABORT("Bad talloc magic value - unknown value");
+ }
}
return tc;
}
@@ -152,10 +162,17 @@ do { \
/*
return the parent chunk of a pointer
*/
-static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
while (tc->prev) tc=tc->prev;
+
return tc->parent;
}
@@ -165,23 +182,32 @@ void *talloc_parent(const void *ptr)
return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
}
+/*
+ find parents name
+*/
+const char *talloc_parent_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return tc? tc->name : NULL;
+}
+
/*
Allocate a bit of memory as a child of an existing pointer
*/
-void *_talloc(const void *context, size_t size)
+static inline void *__talloc(const void *context, size_t size)
{
struct talloc_chunk *tc;
- if (context == NULL) {
+ if (unlikely(context == NULL)) {
context = null_context;
}
- if (size >= MAX_TALLOC_SIZE) {
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
return NULL;
}
- tc = malloc(TC_HDR_SIZE+size);
- if (tc == NULL) return NULL;
+ tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
+ if (unlikely(tc == NULL)) return NULL;
tc->size = size;
tc->flags = TALLOC_MAGIC;
@@ -190,16 +216,19 @@ void *_talloc(const void *context, size_t size)
tc->name = NULL;
tc->refs = NULL;
- if (context) {
+ if (likely(context)) {
struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
- tc->parent = parent;
-
if (parent->child) {
parent->child->parent = NULL;
+ tc->next = parent->child;
+ tc->next->prev = tc;
+ } else {
+ tc->next = NULL;
}
-
- _TLIST_ADD(parent->child, tc);
+ tc->parent = parent;
+ tc->prev = NULL;
+ parent->child = tc;
} else {
tc->next = tc->prev = tc->parent = NULL;
}
@@ -207,14 +236,13 @@ void *_talloc(const void *context, size_t size)
return TC_PTR_FROM_CHUNK(tc);
}
-
/*
setup a destructor to be called on free of a pointer
the destructor should return 0 on success, or -1 on failure.
if the destructor fails then the free is failed, and the memory can
be continued to be used
*/
-void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
+void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->destructor = destructor;
@@ -223,28 +251,54 @@ void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
/*
increase the reference count on a piece of memory.
*/
-void talloc_increase_ref_count(const void *ptr)
+int talloc_increase_ref_count(const void *ptr)
{
- talloc_reference(null_context, ptr);
+ if (unlikely(!talloc_reference(null_context, ptr))) {
+ return -1;
+ }
+ return 0;
}
/*
helper for talloc_reference()
+
+ this is referenced by a function pointer and should not be inline
*/
-static int talloc_reference_destructor(void *ptr)
+static int talloc_reference_destructor(struct talloc_reference_handle *handle)
{
- struct talloc_reference_handle *handle = ptr;
- struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
- struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
- if (tc1->destructor != (talloc_destructor_t)-1) {
- tc1->destructor = NULL;
- }
- _TLIST_REMOVE(tc2->refs, handle);
- talloc_free(handle);
+ struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
+ _TLIST_REMOVE(ptr_tc->refs, handle);
return 0;
}
/*
+ more efficient way to add a name to a pointer - the name must point to a
+ true string constant
+*/
+static inline void _talloc_set_name_const(const void *ptr, const char *name)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = name;
+}
+
+/*
+ internal talloc_named_const()
+*/
+static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
+{
+ void *ptr;
+
+ ptr = __talloc(context, size);
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ _talloc_set_name_const(ptr, name);
+
+ return ptr;
+}
+
+/*
make a secondary reference to a pointer, hanging off the given context.
the pointer remains valid until both the original caller and this given
context are freed.
@@ -253,16 +307,17 @@ static int talloc_reference_destructor(void *ptr)
same underlying data, and you want to be able to free the two instances separately,
and in either order
*/
-void *talloc_reference(const void *context, const void *ptr)
+void *_talloc_reference(const void *context, const void *ptr)
{
struct talloc_chunk *tc;
struct talloc_reference_handle *handle;
- if (ptr == NULL) return NULL;
+ if (unlikely(ptr == NULL)) return NULL;
tc = talloc_chunk_from_ptr(ptr);
- handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
-
- if (handle == NULL) return NULL;
+ handle = (struct talloc_reference_handle *)_talloc_named_const(context,
+ sizeof(struct talloc_reference_handle),
+ TALLOC_MAGIC_REFERENCE);
+ if (unlikely(handle == NULL)) return NULL;
/* note that we hang the destructor off the handle, not the
main context as that allows the caller to still setup their
@@ -273,17 +328,163 @@ void *talloc_reference(const void *context, const void *ptr)
return handle->ptr;
}
+
+/*
+ internal talloc_free call
+*/
+static inline int _talloc_free(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (unlikely(ptr == NULL)) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(tc->refs)) {
+ int is_child;
+ /* check this is a reference from a child or grantchild
+ * back to it's parent or grantparent
+ *
+ * in that case we need to remove the reference and
+ * call another instance of talloc_free() on the current
+ * pointer.
+ */
+ is_child = talloc_is_parent(tc->refs, ptr);
+ _talloc_free(tc->refs);
+ if (is_child) {
+ return _talloc_free(ptr);
+ }
+ return -1;
+ }
+
+ if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
+ /* we have a free loop - stop looping */
+ return 0;
+ }
+
+ if (unlikely(tc->destructor)) {
+ talloc_destructor_t d = tc->destructor;
+ if (d == (talloc_destructor_t)-1) {
+ return -1;
+ }
+ tc->destructor = (talloc_destructor_t)-1;
+ if (d(ptr) == -1) {
+ tc->destructor = d;
+ return -1;
+ }
+ tc->destructor = NULL;
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
+
+ while (tc->child) {
+ /* we need to work out who will own an abandoned child
+ if it cannot be freed. In priority order, the first
+ choice is owner of any remaining reference to this
+ pointer, the second choice is our parent, and the
+ final choice is the null context. */
+ void *child = TC_PTR_FROM_CHUNK(tc->child);
+ const void *new_parent = null_context;
+ if (unlikely(tc->child->refs)) {
+ struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ if (unlikely(_talloc_free(child) == -1)) {
+ if (new_parent == null_context) {
+ struct talloc_chunk *p = talloc_parent_chunk(ptr);
+ if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+ }
+ talloc_steal(new_parent, child);
+ }
+ }
+
+ tc->flags |= TALLOC_FLAG_FREE;
+ free(tc);
+ return 0;
+}
+
+/*
+ move a lump of memory from one talloc context to another return the
+ ptr on success, or NULL if it could not be transferred.
+ passing NULL as ptr will always return NULL with no side effects.
+*/
+void *_talloc_steal(const void *new_ctx, const void *ptr)
+{
+ struct talloc_chunk *tc, *new_tc;
+
+ if (unlikely(!ptr)) {
+ return NULL;
+ }
+
+ if (unlikely(new_ctx == NULL)) {
+ new_ctx = null_context;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (unlikely(new_ctx == NULL)) {
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = tc->next = tc->prev = NULL;
+ return discard_const_p(void, ptr);
+ }
+
+ new_tc = talloc_chunk_from_ptr(new_ctx);
+
+ if (unlikely(tc == new_tc || tc->parent == new_tc)) {
+ return discard_const_p(void, ptr);
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = new_tc;
+ if (new_tc->child) new_tc->child->parent = NULL;
+ _TLIST_ADD(new_tc->child, tc);
+
+ return discard_const_p(void, ptr);
+}
+
+
+
/*
remove a secondary reference to a pointer. This undo's what
talloc_reference() has done. The context and pointer arguments
must match those given to a talloc_reference()
*/
-static int talloc_unreference(const void *context, const void *ptr)
+static inline int talloc_unreference(const void *context, const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
struct talloc_reference_handle *h;
- if (context == NULL) {
+ if (unlikely(context == NULL)) {
context = null_context;
}
@@ -299,10 +500,7 @@ static int talloc_unreference(const void *context, const void *ptr)
return -1;
}
- talloc_set_destructor(h, NULL);
- _TLIST_REMOVE(tc->refs, h);
- talloc_free(h);
- return 0;
+ return _talloc_free(h);
}
/*
@@ -339,7 +537,7 @@ int talloc_unlink(const void *context, void *ptr)
tc_p = talloc_chunk_from_ptr(ptr);
if (tc_p->refs == NULL) {
- return talloc_free(ptr);
+ return _talloc_free(ptr);
}
new_p = talloc_parent_chunk(tc_p->refs);
@@ -361,37 +559,31 @@ int talloc_unlink(const void *context, void *ptr)
/*
add a name to an existing pointer - va_list version
*/
-static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
tc->name = talloc_vasprintf(ptr, fmt, ap);
- if (tc->name) {
- talloc_set_name_const(tc->name, ".name");
+ if (likely(tc->name)) {
+ _talloc_set_name_const(tc->name, ".name");
}
+ return tc->name;
}
/*
add a name to an existing pointer
*/
-void talloc_set_name(const void *ptr, const char *fmt, ...)
+const char *talloc_set_name(const void *ptr, const char *fmt, ...)
{
+ const char *name;
va_list ap;
va_start(ap, fmt);
- talloc_set_name_v(ptr, fmt, ap);
+ name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
+ return name;
}
-/*
- more efficient way to add a name to a pointer - the name must point to a
- true string constant
-*/
-void talloc_set_name_const(const void *ptr, const char *name)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- tc->name = name;
-}
/*
create a named talloc pointer. Any talloc pointer can be named, and
@@ -402,33 +594,20 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
{
va_list ap;
void *ptr;
+ const char *name;
- ptr = _talloc(context, size);
- if (ptr == NULL) return NULL;
+ ptr = __talloc(context, size);
+ if (unlikely(ptr == NULL)) return NULL;
va_start(ap, fmt);
- talloc_set_name_v(ptr, fmt, ap);
+ name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
- return ptr;
-}
-
-/*
- create a named talloc pointer. Any talloc pointer can be named, and
- talloc_named() operates just like talloc() except that it allows you
- to name the pointer.
-*/
-void *talloc_named_const(const void *context, size_t size, const char *name)
-{
- void *ptr;
-
- ptr = _talloc(context, size);
- if (ptr == NULL) {
+ if (unlikely(name == NULL)) {
+ _talloc_free(ptr);
return NULL;
}
- talloc_set_name_const(ptr, name);
-
return ptr;
}
@@ -438,10 +617,10 @@ void *talloc_named_const(const void *context, size_t size, const char *name)
const char *talloc_get_name(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- if (tc->name == TALLOC_MAGIC_REFERENCE) {
+ if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
return ".reference";
}
- if (tc->name) {
+ if (likely(tc->name)) {
return tc->name;
}
return "UNNAMED";
@@ -455,9 +634,9 @@ const char *talloc_get_name(const void *ptr)
void *talloc_check_name(const void *ptr, const char *name)
{
const char *pname;
- if (ptr == NULL) return NULL;
+ if (unlikely(ptr == NULL)) return NULL;
pname = talloc_get_name(ptr);
- if (pname == name || strcmp(pname, name) == 0) {
+ if (likely(pname == name || strcmp(pname, name) == 0)) {
return discard_const_p(void, ptr);
}
return NULL;
@@ -471,16 +650,27 @@ void *talloc_init(const char *fmt, ...)
{
va_list ap;
void *ptr;
+ const char *name;
+ /*
+ * samba3 expects talloc_report_depth_cb(NULL, ...)
+ * reports all talloc'ed memory, so we need to enable
+ * null_tracking
+ */
talloc_enable_null_tracking();
- ptr = _talloc(NULL, 0);
- if (ptr == NULL) return NULL;
+ ptr = __talloc(NULL, 0);
+ if (unlikely(ptr == NULL)) return NULL;
va_start(ap, fmt);
- talloc_set_name_v(ptr, fmt, ap);
+ name = talloc_set_name_v(ptr, fmt, ap);
va_end(ap);
+ if (unlikely(name == NULL)) {
+ _talloc_free(ptr);
+ return NULL;
+ }
+
return ptr;
}
@@ -493,7 +683,7 @@ void talloc_free_children(void *ptr)
{
struct talloc_chunk *tc;
- if (ptr == NULL) {
+ if (unlikely(ptr == NULL)) {
return;
}
@@ -507,11 +697,11 @@ void talloc_free_children(void *ptr)
final choice is the null context. */
void *child = TC_PTR_FROM_CHUNK(tc->child);
const void *new_parent = null_context;
- if (tc->child->refs) {
+ if (unlikely(tc->child->refs)) {
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
- if (talloc_free(child) == -1) {
+ if (unlikely(_talloc_free(child) == -1)) {
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
@@ -522,6 +712,32 @@ void talloc_free_children(void *ptr)
}
/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+void *_talloc(const void *context, size_t size)
+{
+ return __talloc(context, size);
+}
+
+/*
+ externally callable talloc_set_name_const()
+*/
+void talloc_set_name_const(const void *ptr, const char *name)
+{
+ _talloc_set_name_const(ptr, name);
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+ return _talloc_named_const(context, size, name);
+}
+
+/*
free a talloc pointer. This also frees all child pointers of this
pointer recursively
@@ -531,61 +747,7 @@ void talloc_free_children(void *ptr)
*/
int talloc_free(void *ptr)
{
- struct talloc_chunk *tc;
-
- if (ptr == NULL) {
- return -1;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (tc->refs) {
- int is_child;
- struct talloc_reference_handle *handle = tc->refs;
- is_child = talloc_is_parent(handle, handle->ptr);
- talloc_reference_destructor(tc->refs);
- if (is_child) {
- return talloc_free(ptr);
- }
- return -1;
- }
-
- if (tc->flags & TALLOC_FLAG_LOOP) {
- /* we have a free loop - stop looping */
- return 0;
- }
-
- if (tc->destructor) {
- talloc_destructor_t d = tc->destructor;
- if (d == (talloc_destructor_t)-1) {
- return -1;
- }
- tc->destructor = (talloc_destructor_t)-1;
- if (d(ptr) == -1) {
- tc->destructor = d;
- return -1;
- }
- tc->destructor = NULL;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
-
- talloc_free_children(ptr);
-
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->flags |= TALLOC_FLAG_FREE;
-
- free(tc);
- return 0;
+ return _talloc_free(ptr);
}
@@ -600,24 +762,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
void *new_ptr;
/* size zero is equivalent to free() */
- if (size == 0) {
- talloc_free(ptr);
+ if (unlikely(size == 0)) {
+ _talloc_free(ptr);
return NULL;
}
- if (size >= MAX_TALLOC_SIZE) {
+ if (unlikely(size >= MAX_TALLOC_SIZE)) {
return NULL;
}
- /* realloc(NULL) is equavalent to malloc() */
+ /* realloc(NULL) is equivalent to malloc() */
if (ptr == NULL) {
- return talloc_named_const(context, size, name);
+ return _talloc_named_const(context, size, name);
}
tc = talloc_chunk_from_ptr(ptr);
/* don't allow realloc on referenced pointers */
- if (tc->refs) {
+ if (unlikely(tc->refs)) {
return NULL;
}
@@ -633,18 +795,18 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
#else
new_ptr = realloc(tc, size + TC_HDR_SIZE);
#endif
- if (!new_ptr) {
+ if (unlikely(!new_ptr)) {
tc->flags &= ~TALLOC_FLAG_FREE;
return NULL;
}
- tc = new_ptr;
+ tc = (struct talloc_chunk *)new_ptr;
tc->flags &= ~TALLOC_FLAG_FREE;
if (tc->parent) {
- tc->parent->child = new_ptr;
+ tc->parent->child = tc;
}
if (tc->child) {
- tc->child->parent = new_ptr;
+ tc->child->parent = tc;
}
if (tc->prev) {
@@ -655,76 +817,31 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
}
tc->size = size;
- talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
+ _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
return TC_PTR_FROM_CHUNK(tc);
}
-/*
- move a lump of memory from one talloc context to another return the
- ptr on success, or NULL if it could not be transferred.
- passing NULL as ptr will always return NULL with no side effects.
+/*
+ a wrapper around talloc_steal() for situations where you are moving a pointer
+ between two structures, and want the old pointer to be set to NULL
*/
-void *talloc_steal(const void *new_ctx, const void *ptr)
+void *_talloc_move(const void *new_ctx, const void *_pptr)
{
- struct talloc_chunk *tc, *new_tc;
-
- if (!ptr) {
- return NULL;
- }
-
- if (new_ctx == NULL) {
- new_ctx = null_context;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (new_ctx == NULL) {
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->parent = tc->next = tc->prev = NULL;
- return discard_const_p(void, ptr);
- }
-
- new_tc = talloc_chunk_from_ptr(new_ctx);
-
- if (tc == new_tc || tc->parent == new_tc) {
- return discard_const_p(void, ptr);
- }
-
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->parent = new_tc;
- if (new_tc->child) new_tc->child->parent = NULL;
- _TLIST_ADD(new_tc->child, tc);
-
- return discard_const_p(void, ptr);
+ const void **pptr = discard_const_p(const void *,_pptr);
+ void *ret = _talloc_steal(new_ctx, *pptr);
+ (*pptr) = NULL;
+ return ret;
}
/*
return the total size of a talloc pool (subtree)
*/
-off_t talloc_total_size(const void *ptr)
+size_t talloc_total_size(const void *ptr)
{
- off_t total = 0;
+ size_t total = 0;
struct talloc_chunk *c, *tc;
-
+
if (ptr == NULL) {
ptr = null_context;
}
@@ -753,9 +870,9 @@ off_t talloc_total_size(const void *ptr)
/*
return the total number of blocks in a talloc pool (subtree)
*/
-off_t talloc_total_blocks(const void *ptr)
+size_t talloc_total_blocks(const void *ptr)
{
- off_t total = 0;
+ size_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
if (tc->flags & TALLOC_FLAG_LOOP) {
@@ -777,11 +894,11 @@ off_t talloc_total_blocks(const void *ptr)
/*
return the number of external references to a pointer
*/
-static int talloc_reference_count(const void *ptr)
+size_t talloc_reference_count(const void *ptr)
{
struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
struct talloc_reference_handle *h;
- int ret = 0;
+ size_t ret = 0;
for (h=tc->refs;h;h=h->next) {
ret++;
@@ -792,80 +909,110 @@ static int talloc_reference_count(const void *ptr)
/*
report on memory usage by all children of a pointer, giving a full tree view
*/
-void talloc_report_depth(const void *ptr, FILE *f, int depth)
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data)
{
- struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ tc = talloc_chunk_from_ptr(ptr);
if (tc->flags & TALLOC_FLAG_LOOP) {
return;
}
- tc->flags |= TALLOC_FLAG_LOOP;
+ callback(ptr, depth, max_depth, 0, private_data);
+ if (max_depth >= 0 && depth >= max_depth) {
+ return;
+ }
+
+ tc->flags |= TALLOC_FLAG_LOOP;
for (c=tc->child;c;c=c->next) {
if (c->name == TALLOC_MAGIC_REFERENCE) {
- struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
- const char *name2 = talloc_get_name(handle->ptr);
- fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
+ struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
+ callback(h->ptr, depth + 1, max_depth, 1, private_data);
} else {
- const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
- fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
- depth*4, "",
- name,
- (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
- (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
- talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
- talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
+ talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
}
}
tc->flags &= ~TALLOC_FLAG_LOOP;
}
-/*
- report on memory usage by all children of a pointer, giving a full tree view
-*/
-void talloc_report_full(const void *ptr, FILE *f)
+static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
{
- if (ptr == NULL) {
- ptr = null_context;
+ const char *name = talloc_get_name(ptr);
+ FILE *f = (FILE *)_f;
+
+ if (is_ref) {
+ fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
+ return;
}
- if (ptr == NULL) return;
- fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
- talloc_get_name(ptr),
+ if (depth == 0) {
+ fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
+ (max_depth < 0 ? "full " :""), name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+ return;
+ }
+
+ fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
+ depth*4, "",
+ name,
(unsigned long)talloc_total_size(ptr),
- (unsigned long)talloc_total_blocks(ptr));
+ (unsigned long)talloc_total_blocks(ptr),
+ (int)talloc_reference_count(ptr), ptr);
+
+#if 0
+ fprintf(f, "content: ");
+ if (talloc_total_size(ptr)) {
+ int tot = talloc_total_size(ptr);
+ int i;
+
+ for (i = 0; i < tot; i++) {
+ if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
+ fprintf(f, "%c", ((char *)ptr)[i]);
+ } else {
+ fprintf(f, "~%02x", ((char *)ptr)[i]);
+ }
+ }
+ }
+ fprintf(f, "\n");
+#endif
+}
- talloc_report_depth(ptr, f, 1);
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
+{
+ talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
fflush(f);
}
/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+ talloc_report_depth_file(ptr, 0, -1, f);
+}
+
+/*
report on memory usage by all children of a pointer
*/
void talloc_report(const void *ptr, FILE *f)
{
- struct talloc_chunk *c, *tc;
-
- if (ptr == NULL) {
- ptr = null_context;
- }
- if (ptr == NULL) return;
-
- fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
- talloc_get_name(ptr),
- (unsigned long)talloc_total_size(ptr),
- (unsigned long)talloc_total_blocks(ptr));
-
- tc = talloc_chunk_from_ptr(ptr);
-
- for (c=tc->child;c;c=c->next) {
- fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
- talloc_get_name(TC_PTR_FROM_CHUNK(c)),
- (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
- (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
- }
- fflush(f);
+ talloc_report_depth_file(ptr, 0, 1, f);
}
/*
@@ -889,92 +1036,23 @@ static void talloc_report_null_full(void)
}
/*
- free allocated global memory
-*/
-
-void talloc_nc_free(void)
-{
- if ( null_context )
- talloc_free( (void*)null_context );
-}
-
-/*
enable tracking of the NULL context
*/
void talloc_enable_null_tracking(void)
{
if (null_context == NULL) {
- null_context = talloc_named_const(NULL, 0, "null_context");
- }
-}
-
-#ifdef _SAMBA_BUILD_
-/* Ugly calls to Samba-specific sprintf_append... JRA. */
-
-/*
- report on memory usage by all children of a pointer, giving a full tree view
-*/
-static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth)
-{
- struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
-
- if (tc->flags & TALLOC_FLAG_LOOP) {
- return;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
-
- for (c=tc->child;c;c=c->next) {
- if (c->name == TALLOC_MAGIC_REFERENCE) {
- struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
- const char *name2 = talloc_get_name(handle->ptr);
-
- sprintf_append(NULL, pps, plen, pbuflen,
- "%*sreference to: %s\n", depth*4, "", name2);
-
- } else {
- const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
-
- sprintf_append(NULL, pps, plen, pbuflen,
- "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
- depth*4, "",
- name,
- (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
- (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
- talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
-
- talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1);
- }
+ null_context = _talloc_named_const(NULL, 0, "null_context");
}
- tc->flags &= ~TALLOC_FLAG_LOOP;
}
/*
- report on memory usage by all children of a pointer
+ disable tracking of the NULL context
*/
-char *talloc_describe_all(void)
+void talloc_disable_null_tracking(void)
{
- ssize_t len = 0;
- size_t buflen = 512;
- char *s = NULL;
-
- if (null_context == NULL) {
- return NULL;
- }
-
- sprintf_append(NULL, &s, &len, &buflen,
- "full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
- talloc_get_name(null_context),
- (unsigned long)talloc_total_size(null_context),
- (unsigned long)talloc_total_blocks(null_context));
-
- if (!s) {
- return NULL;
- }
- talloc_report_depth_str(null_context, &s, &len, &buflen, 1);
- return s;
+ _talloc_free(null_context);
+ null_context = NULL;
}
-#endif
/*
enable leak reporting on exit
@@ -999,7 +1077,7 @@ void talloc_enable_leak_report_full(void)
*/
void *_talloc_zero(const void *ctx, size_t size, const char *name)
{
- void *p = talloc_named_const(ctx, size, name);
+ void *p = _talloc_named_const(ctx, size, name);
if (p) {
memset(p, '\0', size);
@@ -1014,9 +1092,9 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name)
*/
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
{
- void *newp = talloc_named_const(t, size, name);
+ void *newp = _talloc_named_const(t, size, name);
- if (newp) {
+ if (likely(newp)) {
memcpy(newp, p, size);
}
@@ -1032,9 +1110,9 @@ char *talloc_strdup(const void *t, const char *p)
if (!p) {
return NULL;
}
- ret = talloc_memdup(t, p, strlen(p) + 1);
- if (ret) {
- talloc_set_name_const(ret, ret);
+ ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
+ if (likely(ret)) {
+ _talloc_set_name_const(ret, ret);
}
return ret;
}
@@ -1073,21 +1151,19 @@ char *talloc_strndup(const void *t, const char *p, size_t n)
for (len=0; len<n && p[len]; len++) ;
- ret = _talloc(t, len + 1);
+ ret = (char *)__talloc(t, len + 1);
if (!ret) { return NULL; }
memcpy(ret, p, len);
ret[len] = 0;
- talloc_set_name_const(ret, ret);
+ _talloc_set_name_const(ret, ret);
return ret;
}
-#ifndef VA_COPY
-#ifdef HAVE_VA_COPY
-#define VA_COPY(dest, src) va_copy(dest, src)
-#elif defined(HAVE___VA_COPY)
-#define VA_COPY(dest, src) __va_copy(dest, src)
+#ifndef HAVE_VA_COPY
+#ifdef HAVE___VA_COPY
+#define va_copy(dest, src) __va_copy(dest, src)
#else
-#define VA_COPY(dest, src) (dest) = (src)
+#define va_copy(dest, src) (dest) = (src)
#endif
#endif
@@ -1098,18 +1174,20 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
va_list ap2;
char c;
- VA_COPY(ap2, ap);
-
/* this call looks strange, but it makes it work on older solaris boxes */
- if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
+ va_copy(ap2, ap);
+ len = vsnprintf(&c, 1, fmt, ap2);
+ va_end(ap2);
+ if (len < 0) {
return NULL;
}
- ret = _talloc(t, len+1);
+ ret = (char *)__talloc(t, len+1);
if (ret) {
- VA_COPY(ap2, ap);
+ va_copy(ap2, ap);
vsnprintf(ret, len+1, fmt, ap2);
- talloc_set_name_const(ret, ret);
+ va_end(ap2);
+ _talloc_set_name_const(ret, ret);
}
return ret;
@@ -1137,14 +1215,12 @@ char *talloc_asprintf(const void *t, const char *fmt, ...)
* and return @p s, which may have moved. Good for gradually
* accumulating output into a string buffer.
**/
-
-static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-
-static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
{
struct talloc_chunk *tc;
int len, s_len;
va_list ap2;
+ char c;
if (s == NULL) {
return talloc_vasprintf(NULL, fmt, ap);
@@ -1152,10 +1228,13 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
tc = talloc_chunk_from_ptr(s);
- VA_COPY(ap2, ap);
-
s_len = tc->size - 1;
- if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) {
+
+ va_copy(ap2, ap);
+ len = vsnprintf(&c, 1, fmt, ap2);
+ va_end(ap2);
+
+ if (len <= 0) {
/* Either the vsnprintf failed or the format resulted in
* no characters being formatted. In the former case, we
* ought to return NULL, in the latter we ought to return
@@ -1168,10 +1247,10 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
s = talloc_realloc(NULL, s, char, s_len + len+1);
if (!s) return NULL;
- VA_COPY(ap2, ap);
-
+ va_copy(ap2, ap);
vsnprintf(s+s_len, len+1, fmt, ap2);
- talloc_set_name_const(s, s);
+ va_end(ap2);
+ _talloc_set_name_const(s, s);
return s;
}
@@ -1199,7 +1278,7 @@ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char
if (count >= MAX_TALLOC_SIZE/el_size) {
return NULL;
}
- return talloc_named_const(ctx, el_size * count, name);
+ return _talloc_named_const(ctx, el_size * count, name);
}
/*
@@ -1236,10 +1315,15 @@ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
}
+static int talloc_autofree_destructor(void *ptr)
+{
+ autofree_context = NULL;
+ return 0;
+}
+
static void talloc_autofree(void)
{
- talloc_free(cleanup_context);
- cleanup_context = NULL;
+ _talloc_free(autofree_context);
}
/*
@@ -1248,11 +1332,12 @@ static void talloc_autofree(void)
*/
void *talloc_autofree_context(void)
{
- if (cleanup_context == NULL) {
- cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
+ if (autofree_context == NULL) {
+ autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
+ talloc_set_destructor(autofree_context, talloc_autofree_destructor);
atexit(talloc_autofree);
}
- return cleanup_context;
+ return autofree_context;
}
size_t talloc_get_size(const void *context)
@@ -1287,7 +1372,6 @@ void *talloc_find_parent_byname(const void *context, const char *name)
if (tc) {
tc = tc->parent;
}
-
}
return NULL;
}
@@ -1313,12 +1397,13 @@ void talloc_show_parents(const void *context, FILE *file)
tc = tc->parent;
}
}
+ fflush(file);
}
/*
return 1 if ptr is a parent of context
*/
-int talloc_is_parent(const void *context, const char *ptr)
+int talloc_is_parent(const void *context, const void *ptr)
{
struct talloc_chunk *tc;
diff --git a/source/include/talloc.h b/source/lib/talloc/talloc.h
index 17032ac7acc..75c130a2756 100644
--- a/source/include/talloc.h
+++ b/source/lib/talloc/talloc.h
@@ -5,6 +5,7 @@
Samba temporary memory allocation functions
Copyright (C) Andrew Tridgell 2004-2005
+ Copyright (C) Stefan Metzmacher 2006
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
@@ -40,9 +41,44 @@ typedef void TALLOC_CTX;
#define TALLOC_DEPRECATED 0
#endif
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+ if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function) \
+ do { \
+ int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
+ _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+ } while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+ stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
+#else
+#define talloc_set_destructor(ptr, function) \
+ _talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
+#endif
+
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
+
/* useful macros for creating type checked pointers */
#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
@@ -52,29 +88,18 @@ typedef void TALLOC_CTX;
#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
-#define malloc_p(type) (type *)malloc(sizeof(type))
-#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count)
-#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count)
-
-#if 0
-/* Not correct for Samba3. */
-#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__)
-#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__)
-#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__)
-#endif
-
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
-
#if TALLOC_DEPRECATED
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
#define talloc_p(ctx, type) talloc(ctx, type)
@@ -83,43 +108,41 @@ typedef void TALLOC_CTX;
#define talloc_destroy(ctx) talloc_free(ctx)
#endif
-#ifndef PRINTF_ATTRIBUTE
-#if (__GNUC__ >= 3)
-/** Use gcc attribute to check printf fns. a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
-
-
/* The following definitions come from talloc.c */
void *_talloc(const void *context, size_t size);
-void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
-void talloc_increase_ref_count(const void *ptr);
-void *talloc_reference(const void *context, const void *ptr);
+void _talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+int talloc_increase_ref_count(const void *ptr);
+size_t talloc_reference_count(const void *ptr);
+void *_talloc_reference(const void *context, const void *ptr);
int talloc_unlink(const void *context, void *ptr);
-void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void talloc_set_name_const(const void *ptr, const char *name);
void *talloc_named(const void *context, size_t size,
const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
void *talloc_named_const(const void *context, size_t size, const char *name);
const char *talloc_get_name(const void *ptr);
void *talloc_check_name(const void *ptr, const char *name);
-void talloc_report_depth(const void *ptr, FILE *f, int depth);
void *talloc_parent(const void *ptr);
+const char *talloc_parent_name(const void *ptr);
void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
int talloc_free(void *ptr);
+void talloc_free_children(void *ptr);
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
-void *talloc_steal(const void *new_ctx, const void *ptr);
-off_t talloc_total_size(const void *ptr);
-off_t talloc_total_blocks(const void *ptr);
+void *_talloc_steal(const void *new_ctx, const void *ptr);
+void *_talloc_move(const void *new_ctx, const void *pptr);
+size_t talloc_total_size(const void *ptr);
+size_t talloc_total_blocks(const void *ptr);
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data);
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
void talloc_report_full(const void *ptr, FILE *f);
void talloc_report(const void *ptr, FILE *f);
void talloc_enable_null_tracking(void);
+void talloc_disable_null_tracking(void);
void talloc_enable_leak_report(void);
void talloc_enable_leak_report_full(void);
void *_talloc_zero(const void *ctx, size_t size, const char *name);
@@ -128,9 +151,9 @@ char *talloc_strdup(const void *t, const char *p);
char *talloc_strndup(const void *t, const char *p, size_t n);
char *talloc_append_string(const void *t, char *orig, const char *append);
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
-char *talloc_asprintf_append(char *s,
- const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
@@ -139,7 +162,7 @@ void *talloc_autofree_context(void);
size_t talloc_get_size(const void *ctx);
void *talloc_find_parent_byname(const void *ctx, const char *name);
void talloc_show_parents(const void *context, FILE *file);
-int talloc_is_parent(const void *context, const char *ptr);
+int talloc_is_parent(const void *context, const void *ptr);
#endif
diff --git a/source/lib/talloc/talloc.pc.in b/source/lib/talloc/talloc.pc.in
new file mode 100644
index 00000000000..7f9ef754cbd
--- /dev/null
+++ b/source/lib/talloc/talloc.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: talloc
+Description: A hierarchical pool based memory system with destructors
+Version: 4.0
+Libs: @LIBS@ -L${libdir} -ltalloc
+Cflags: -I${includedir} @CFLAGS@
diff --git a/source/lib/talloc/talloc_guide.txt b/source/lib/talloc/talloc_guide.txt
new file mode 100644
index 00000000000..8b252e4ab9b
--- /dev/null
+++ b/source/lib/talloc/talloc_guide.txt
@@ -0,0 +1,653 @@
+Using talloc in Samba4
+----------------------
+
+Andrew Tridgell
+September 2004
+
+The most current version of this document is available at
+ http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt
+
+If you are used to the "old" talloc from Samba3 before 3.0.20 then please read
+this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the
+Samba4 talloc has been ported back to Samba3, so this guide applies to both.
+
+The new talloc is a hierarchical, reference counted memory pool system
+with destructors. Quite a mounthful really, but not too bad once you
+get used to it.
+
+Perhaps the biggest change from Samba3 is that there is no distinction
+between a "talloc context" and a "talloc pointer". Any pointer
+returned from talloc() is itself a valid talloc context. This means
+you can do this:
+
+ struct foo *X = talloc(mem_ctx, struct foo);
+ X->name = talloc_strdup(X, "foo");
+
+and the pointer X->name would be a "child" of the talloc context "X"
+which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx)
+then it is all destroyed, whereas if you do talloc_free(X) then just X
+and X->name are destroyed, and if you do talloc_free(X->name) then
+just the name element of X is destroyed.
+
+If you think about this, then what this effectively gives you is an
+n-ary tree, where you can free any part of the tree with
+talloc_free().
+
+If you find this confusing, then I suggest you run the testsuite to
+watch talloc in action. You may also like to add your own tests to
+testsuite.c to clarify how some particular situation is handled.
+
+
+Performance
+-----------
+
+All the additional features of talloc() over malloc() do come at a
+price. We have a simple performance test in Samba4 that measures
+talloc() versus malloc() performance, and it seems that talloc() is
+about 4% slower than malloc() on my x86 Debian Linux box. For Samba,
+the great reduction in code complexity that we get by using talloc
+makes this worthwhile, especially as the total overhead of
+talloc/malloc in Samba is already quite small.
+
+
+talloc API
+----------
+
+The following is a complete guide to the talloc API. Read it all at
+least twice.
+
+Multi-threading
+---------------
+
+talloc itself does not deal with threads. It is thread-safe (assuming
+the underlying "malloc" is), as long as each thread uses different
+memory contexts.
+If two threads uses the same context then they need to synchronize in
+order to be safe. In particular:
+- when using talloc_enable_leak_report(), giving directly NULL as a
+parent context implicitly refers to a hidden "null context" global
+variable, so this should not be used in a multi-threaded environment
+without proper synchronization ;
+- the context returned by talloc_autofree_context() is also global so
+shouldn't be used by several threads simultaneously without
+synchronization.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc(const void *context, type);
+
+The talloc() macro is the core of the talloc library. It takes a
+memory context and a type, and returns a pointer to a new area of
+memory of the given type.
+
+The returned pointer is itself a talloc context, so you can use it as
+the context argument to more calls to talloc if you wish.
+
+The returned pointer is a "child" of the supplied context. This means
+that if you talloc_free() the context then the new child disappears as
+well. Alternatively you can free just the child.
+
+The context argument to talloc() can be NULL, in which case a new top
+level context is created.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_size(const void *context, size_t size);
+
+The function talloc_size() should be used when you don't have a
+convenient type to pass to talloc(). Unlike talloc(), it is not type
+safe (as it returns a void *), so you are on your own for type checking.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);
+
+The talloc_ptrtype() macro should be used when you have a pointer and
+want to allocate memory to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free(void *ptr);
+
+The talloc_free() function frees a piece of talloc memory, and all its
+children. You can call talloc_free() on any pointer returned by
+talloc().
+
+The return value of talloc_free() indicates success or failure, with 0
+returned for success and -1 for failure. The only possible failure
+condition is if the pointer had a destructor attached to it and the
+destructor returned -1. See talloc_set_destructor() for details on
+destructors.
+
+If this pointer has an additional parent when talloc_free() is called
+then the memory is not actually released, but instead the most
+recently established parent is destroyed. See talloc_reference() for
+details on establishing additional parents.
+
+For more control on which parent is removed, see talloc_unlink()
+
+talloc_free() operates recursively on its children.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free_children(void *ptr);
+
+The talloc_free_children() walks along the list of all children of a
+talloc context and talloc_free()s only the children, not the context
+itself.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reference(const void *context, const void *ptr);
+
+The talloc_reference() function makes "context" an additional parent
+of "ptr".
+
+The return value of talloc_reference() is always the original pointer
+"ptr", unless talloc ran out of memory in creating the reference in
+which case it will return NULL (each additional reference consumes
+around 48 bytes of memory on intel x86 platforms).
+
+If "ptr" is NULL, then the function is a no-op, and simply returns NULL.
+
+After creating a reference you can free it in one of the following
+ways:
+
+ - you can talloc_free() any parent of the original pointer. That
+ will reduce the number of parents of this pointer by 1, and will
+ cause this pointer to be freed if it runs out of parents.
+
+ - you can talloc_free() the pointer itself. That will destroy the
+ most recently established parent to the pointer and leave the
+ pointer as a child of its current parent.
+
+For more control on which parent to remove, see talloc_unlink()
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_unlink(const void *context, const void *ptr);
+
+The talloc_unlink() function removes a specific parent from ptr. The
+context passed must either be a context used in talloc_reference()
+with this pointer, or must be a direct parent of ptr.
+
+Note that if the parent has already been removed using talloc_free()
+then this function will fail and will return -1. Likewise, if "ptr"
+is NULL, then the function will make no modifications and return -1.
+
+Usually you can just use talloc_free() instead of talloc_unlink(), but
+sometimes it is useful to have the additional control on which parent
+is removed.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+
+The function talloc_set_destructor() sets the "destructor" for the
+pointer "ptr". A destructor is a function that is called when the
+memory used by a pointer is about to be released. The destructor
+receives the pointer as an argument, and should return 0 for success
+and -1 for failure.
+
+The destructor can do anything it wants to, including freeing other
+pieces of memory. A common use for destructors is to clean up
+operating system resources (such as open file descriptors) contained
+in the structure the destructor is placed on.
+
+You can only place one destructor on a pointer. If you need more than
+one destructor then you can create a zero-length child of the pointer
+and place an additional destructor on that.
+
+To remove a destructor call talloc_set_destructor() with NULL for the
+destructor.
+
+If your destructor attempts to talloc_free() the pointer that it is
+the destructor for then talloc_free() will return -1 and the free will
+be ignored. This would be a pointless operation anyway, as the
+destructor is only called when the memory is just about to go away.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_increase_ref_count(const void *ptr);
+
+The talloc_increase_ref_count(ptr) function is exactly equivalent to:
+
+ talloc_reference(NULL, ptr);
+
+You can use either syntax, depending on which you think is clearer in
+your code.
+
+It returns 0 on success and -1 on failure.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_reference_count(const void *ptr);
+
+Return the number of references to the pointer.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name(const void *ptr, const char *fmt, ...);
+
+Each talloc pointer has a "name". The name is used principally for
+debugging purposes, although it is also possible to set and get the
+name on a pointer in as a way of "marking" pointers in your code.
+
+The main use for names on pointer is for "talloc reports". See
+talloc_report() and talloc_report_full() for details. Also see
+talloc_enable_leak_report() and talloc_enable_leak_report_full().
+
+The talloc_set_name() function allocates memory as a child of the
+pointer. It is logically equivalent to:
+ talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));
+
+Note that multiple calls to talloc_set_name() will allocate more
+memory without releasing the name. All of the memory is released when
+the ptr is freed using talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name_const(const void *ptr, const char *name);
+
+The function talloc_set_name_const() is just like talloc_set_name(),
+but it takes a string constant, and is much faster. It is extensively
+used by the "auto naming" macros, such as talloc_p().
+
+This function does not allocate any memory. It just copies the
+supplied pointer into the internal representation of the talloc
+ptr. This means you must not pass a name pointer to memory that will
+disappear before the ptr is freed with talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named(const void *context, size_t size, const char *fmt, ...);
+
+The talloc_named() function creates a named talloc pointer. It is
+equivalent to:
+
+ ptr = talloc_size(context, size);
+ talloc_set_name(ptr, fmt, ....);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named_const(const void *context, size_t size, const char *name);
+
+This is equivalent to:
+
+ ptr = talloc_size(context, size);
+ talloc_set_name_const(ptr, name);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+const char *talloc_get_name(const void *ptr);
+
+This returns the current name for the given talloc pointer. See
+talloc_set_name() for details.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_init(const char *fmt, ...);
+
+This function creates a zero length named talloc context as a top
+level context. It is equivalent to:
+
+ talloc_named(NULL, 0, fmt, ...);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_new(void *ctx);
+
+This is a utility macro that creates a new memory context hanging
+off an exiting context, automatically naming it "talloc_new: __location__"
+where __location__ is the source line it is called from. It is
+particularly useful for creating a new temporary working context.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_realloc(const void *context, void *ptr, type, count);
+
+The talloc_realloc() macro changes the size of a talloc
+pointer. The "count" argument is the number of elements of type "type"
+that you want the resulting pointer to hold.
+
+talloc_realloc() has the following equivalences:
+
+ talloc_realloc(context, NULL, type, 1) ==> talloc(context, type);
+ talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N);
+ talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr);
+
+The "context" argument is only used if "ptr" is NULL, otherwise it is
+ignored.
+
+talloc_realloc() returns the new pointer, or NULL on failure. The call
+will fail either due to a lack of memory, or because the pointer has
+more than one parent (see talloc_reference()).
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_size(const void *context, void *ptr, size_t size);
+
+the talloc_realloc_size() function is useful when the type is not
+known so the typesafe talloc_realloc() cannot be used.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_steal(const void *new_ctx, const void *ptr);
+
+The talloc_steal() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_steal() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+NOTE: It is possible to produce loops in the parent/child relationship
+if you are not careful with talloc_steal(). No guarantees are provided
+as to your sanity or the safety of your data if you do this.
+
+talloc_steal (new_ctx, NULL) will return NULL with no sideeffects.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_size(const void *ptr);
+
+The talloc_total_size() function returns the total size in bytes used
+by this pointer and all child pointers. Mostly useful for debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_blocks(const void *ptr);
+
+The talloc_total_blocks() function returns the total memory block
+count used by this pointer and all child pointers. Mostly useful for
+debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *priv),
+ void *priv);
+
+This provides a more flexible reports than talloc_report(). It
+will recursively call the callback for the entire tree of memory
+referenced by the pointer. References in the tree are passed with
+is_ref = 1 and the pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is
+printed for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full()
+has been called.
+
+The recursion is stopped when depth >= max_depth.
+max_depth = -1 means only stop at leaf nodes.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+
+This provides a more flexible reports than talloc_report(). It
+will let you specify the depth and max_depth.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report(const void *ptr, FILE *f);
+
+The talloc_report() function prints a summary report of all memory
+used by ptr. One line of report is printed for each immediate child of
+ptr, showing the total memory and number of blocks used by that child.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_full(const void *ptr, FILE *f);
+
+This provides a more detailed report than talloc_report(). It will
+recursively print the ensire tree of memory referenced by the
+pointer. References in the tree are shown by giving the name of the
+pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report(void);
+
+This enables calling of talloc_report(NULL, stderr) when the program
+exits. In Samba4 this is enabled by using the --leak-report command
+line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical talloc report:
+
+talloc report on 'null_context' (total 267 bytes in 15 blocks)
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(UTF8,CP850) contains 42 bytes in 2 blocks
+ libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks
+ iconv(CP850,UTF8) contains 42 bytes in 2 blocks
+ iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks
+ iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report_full(void);
+
+This enables calling of talloc_report_full(NULL, stderr) when the
+program exits. In Samba4 this is enabled by using the
+--leak-report-full command line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical full report:
+
+full talloc report on 'root' (total 18 bytes in 8 blocks)
+ p1 contains 18 bytes in 7 blocks (ref 0)
+ r1 contains 13 bytes in 2 blocks (ref 0)
+ reference to: p2
+ p2 contains 1 bytes in 1 blocks (ref 1)
+ x3 contains 1 bytes in 1 blocks (ref 0)
+ x2 contains 1 bytes in 1 blocks (ref 0)
+ x1 contains 1 bytes in 1 blocks (ref 0)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_null_tracking(void);
+
+This enables tracking of the NULL memory context without enabling leak
+reporting on exit. Useful for when you want to do your own leak
+reporting call via talloc_report_null_full();
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_disable_null_tracking(void);
+
+This disables tracking of the NULL memory context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_zero(const void *ctx, type);
+
+The talloc_zero() macro is equivalent to:
+
+ ptr = talloc(ctx, type);
+ if (ptr) memset(ptr, 0, sizeof(type));
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_zero_size(const void *ctx, size_t size)
+
+The talloc_zero_size() function is useful when you don't have a known type
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_memdup(const void *ctx, const void *p, size_t size);
+
+The talloc_memdup() function is equivalent to:
+
+ ptr = talloc_size(ctx, size);
+ if (ptr) memcpy(ptr, p, size);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strdup(const void *ctx, const char *p);
+
+The talloc_strdup() function is equivalent to:
+
+ ptr = talloc_size(ctx, strlen(p)+1);
+ if (ptr) memcpy(ptr, p, strlen(p)+1);
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+ talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strndup(const void *t, const char *p, size_t n);
+
+The talloc_strndup() function is the talloc equivalent of the C
+library function strndup()
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap);
+
+The talloc_vasprintf() function is the talloc equivalent of the C
+library function vasprintf()
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf(const void *t, const char *fmt, ...);
+
+The talloc_asprintf() function is the talloc equivalent of the C
+library function asprintf()
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+ talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the given string.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_array(const void *ctx, type, uint_t count);
+
+The talloc_array() macro is equivalent to:
+
+ (type *)talloc_size(ctx, sizeof(type) * count);
+
+except that it provides integer overflow protection for the multiply,
+returning NULL if the multiply overflows.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_array_size(const void *ctx, size_t size, uint_t count);
+
+The talloc_array_size() function is useful when the type is not
+known. It operates in the same way as talloc_array(), but takes a size
+instead of a type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);
+
+The talloc_ptrtype() macro should be used when you have a pointer to an array
+and want to allocate memory of an array to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size);
+
+This is a non-macro version of talloc_realloc(), which is useful
+as libraries sometimes want a ralloc function pointer. A realloc()
+implementation encapsulates the functionality of malloc(), free() and
+realloc() in one call, which is why it is useful to be able to pass
+around a single function pointer.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_autofree_context(void);
+
+This is a handy utility function that returns a talloc context
+which will be automatically freed on program exit. This can be used
+to reduce the noise in memory leak reports.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_check_name(const void *ptr, const char *name);
+
+This function checks if a pointer has the specified name. If it does
+then the pointer is returned. It it doesn't then NULL is returned.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_get_type(const void *ptr, type);
+
+This macro allows you to do type checking on talloc pointers. It is
+particularly useful for void* private pointers. It is equivalent to
+this:
+
+ (type *)talloc_check_name(ptr, #type)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_set_type(const void *ptr, type);
+
+This macro allows you to force the name of a pointer to be a
+particular type. This can be used in conjunction with
+talloc_get_type() to do type checking on void* pointers.
+
+It is equivalent to this:
+ talloc_set_name_const(ptr, #type)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_get_size(const void *ctx);
+
+This function lets you know the amount of memory alloced so far by
+this context. It does NOT account for subcontext memory.
+This can be used to calculate the size of an array.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+
+Find a parent memory context of the current context that has the given
+name. This can be very useful in complex programs where it may be
+difficult to pass all information down to the level you need, but you
+know the structure you want is a parent of another context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_find_parent_bytype(ctx, type);
+
+Like talloc_find_parent_byname() but takes a type, making it typesafe.
+
diff --git a/source/lib/talloc/testsuite.c b/source/lib/talloc/testsuite.c
new file mode 100644
index 00000000000..f51252e57bc
--- /dev/null
+++ b/source/lib/talloc/testsuite.c
@@ -0,0 +1,1061 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local testing of talloc routines.
+
+ Copyright (C) Andrew Tridgell 2004
+
+ ** NOTE! The following LGPL license applies to the talloc
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "replace.h"
+#include "system/time.h"
+#include "talloc.h"
+
+static struct timeval timeval_current(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv;
+}
+
+static double timeval_elapsed(struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ return (tv2.tv_sec - tv->tv_sec) +
+ (tv2.tv_usec - tv->tv_usec)*1.0e-6;
+}
+
+#define torture_assert(test, expr, str) if (!(expr)) { \
+ printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
+ test, __location__, #expr, str); \
+ return false; \
+}
+
+#define torture_assert_str_equal(test, arg1, arg2, desc) \
+ if (strcmp(arg1, arg2)) { \
+ printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
+ test, __location__, arg1, arg2, desc); \
+ return false; \
+ }
+
+#if _SAMBA_BUILD_==3
+#ifdef malloc
+#undef malloc
+#endif
+#ifdef strdup
+#undef strdup
+#endif
+#endif
+
+#define CHECK_SIZE(test, ptr, tsize) do { \
+ if (talloc_total_size(ptr) != (tsize)) { \
+ printf("failed: %s [\nwrong '%s' tree size: got %u expected %u\n]\n", \
+ test, #ptr, \
+ (unsigned)talloc_total_size(ptr), \
+ (unsigned)tsize); \
+ talloc_report_full(ptr, stdout); \
+ return false; \
+ } \
+} while (0)
+
+#define CHECK_BLOCKS(test, ptr, tblocks) do { \
+ if (talloc_total_blocks(ptr) != (tblocks)) { \
+ printf("failed: %s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \
+ test, #ptr, \
+ (unsigned)talloc_total_blocks(ptr), \
+ (unsigned)tblocks); \
+ talloc_report_full(ptr, stdout); \
+ return false; \
+ } \
+} while (0)
+
+#define CHECK_PARENT(test, ptr, parent) do { \
+ if (talloc_parent(ptr) != (parent)) { \
+ printf("failed: %s [\n'%s' has wrong parent: got %p expected %p\n]\n", \
+ test, #ptr, \
+ talloc_parent(ptr), \
+ (parent)); \
+ talloc_report_full(ptr, stdout); \
+ talloc_report_full(parent, stdout); \
+ talloc_report_full(NULL, stdout); \
+ return false; \
+ } \
+} while (0)
+
+
+/*
+ test references
+*/
+static bool test_ref1(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref1 [\nSINGLE REFERENCE FREE\n]\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ p2 = talloc_named_const(p1, 1, "p2");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 2, "x2");
+ talloc_named_const(p1, 3, "x3");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", p1, 5);
+ CHECK_BLOCKS("ref1", p2, 1);
+ CHECK_BLOCKS("ref1", r1, 2);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", p1, 5);
+ CHECK_BLOCKS("ref1", p2, 1);
+ CHECK_BLOCKS("ref1", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref1", r1, 1);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(NULL, stderr);
+
+ fprintf(stderr, "Testing NULL\n");
+ if (talloc_reference(root, NULL)) {
+ return false;
+ }
+
+ CHECK_BLOCKS("ref1", root, 1);
+
+ CHECK_SIZE("ref1", root, 0);
+
+ talloc_free(root);
+ printf("success: ref1\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref2(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref2 [\nDOUBLE REFERENCE FREE\n]\n");
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 5);
+ CHECK_BLOCKS("ref2", p2, 1);
+ CHECK_BLOCKS("ref2", r1, 2);
+
+ fprintf(stderr, "Freeing ref\n");
+ talloc_free(ref);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 5);
+ CHECK_BLOCKS("ref2", p2, 1);
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", p1, 4);
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref2", r1, 1);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref2", root, 0);
+
+ talloc_free(root);
+ printf("success: ref2\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref3(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref3 [\nPARENT REFERENCE FREE\n]\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ p2 = talloc_named_const(root, 1, "p2");
+ r1 = talloc_named_const(p1, 1, "r1");
+ ref = talloc_reference(p2, r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref3", p1, 2);
+ CHECK_BLOCKS("ref3", p2, 2);
+ CHECK_BLOCKS("ref3", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref3", p2, 2);
+ CHECK_BLOCKS("ref3", r1, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref3", root, 0);
+
+ talloc_free(root);
+
+ printf("success: ref3\n");
+ return true;
+}
+
+/*
+ test references
+*/
+static bool test_ref4(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: ref4 [\nREFERRER REFERENCE FREE\n]\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(root, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 5);
+ CHECK_BLOCKS("ref4", p2, 1);
+ CHECK_BLOCKS("ref4", r1, 2);
+
+ fprintf(stderr, "Freeing r1\n");
+ talloc_free(r1);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 5);
+ CHECK_BLOCKS("ref4", p2, 1);
+
+ fprintf(stderr, "Freeing p2\n");
+ talloc_free(p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("ref4", p1, 4);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("ref4", root, 0);
+
+ talloc_free(root);
+
+ printf("success: ref4\n");
+ return true;
+}
+
+
+/*
+ test references
+*/
+static bool test_unlink1(void)
+{
+ void *root, *p1, *p2, *ref, *r1;
+
+ printf("test: unlink [\nUNLINK\n]\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "p1");
+ talloc_named_const(p1, 1, "x1");
+ talloc_named_const(p1, 1, "x2");
+ talloc_named_const(p1, 1, "x3");
+ p2 = talloc_named_const(p1, 1, "p2");
+
+ r1 = talloc_named_const(p1, 1, "r1");
+ ref = talloc_reference(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("unlink", p1, 7);
+ CHECK_BLOCKS("unlink", p2, 1);
+ CHECK_BLOCKS("unlink", r1, 2);
+
+ fprintf(stderr, "Unreferencing r1\n");
+ talloc_unlink(r1, p2);
+ talloc_report_full(root, stderr);
+
+ CHECK_BLOCKS("unlink", p1, 6);
+ CHECK_BLOCKS("unlink", p2, 1);
+ CHECK_BLOCKS("unlink", r1, 1);
+
+ fprintf(stderr, "Freeing p1\n");
+ talloc_free(p1);
+ talloc_report_full(root, stderr);
+
+ CHECK_SIZE("unlink", root, 0);
+
+ talloc_free(root);
+
+ printf("success: unlink\n");
+ return true;
+}
+
+static int fail_destructor(void *ptr)
+{
+ return -1;
+}
+
+/*
+ miscellaneous tests to try to get a higher test coverage percentage
+*/
+static bool test_misc(void)
+{
+ void *root, *p1;
+ char *p2;
+ double *d;
+ const char *name;
+
+ printf("test: misc [\nMISCELLANEOUS\n]\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_size(root, 0x7fffffff);
+ torture_assert("misc", !p1, "failed: large talloc allowed\n");
+
+ p1 = talloc_strdup(root, "foo");
+ talloc_increase_ref_count(p1);
+ talloc_increase_ref_count(p1);
+ talloc_increase_ref_count(p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_free(p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_unlink(NULL, p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ p2 = talloc_strdup(p1, "foo");
+ torture_assert("misc", talloc_unlink(root, p2) == -1,
+ "failed: talloc_unlink() of non-reference context should return -1\n");
+ torture_assert("misc", talloc_unlink(p1, p2) == 0,
+ "failed: talloc_unlink() of parent should succeed\n");
+ talloc_free(p1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+
+ name = talloc_set_name(p1, "my name is %s", "foo");
+ torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
+ "failed: wrong name after talloc_set_name(my name is foo)");
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+
+ talloc_set_name_const(p1, NULL);
+ torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
+ "failed: wrong name after talloc_set_name(NULL)");
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+
+ torture_assert("misc", talloc_free(NULL) == -1,
+ "talloc_free(NULL) should give -1\n");
+
+ talloc_set_destructor(p1, fail_destructor);
+ torture_assert("misc", talloc_free(p1) == -1,
+ "Failed destructor should cause talloc_free to fail\n");
+ talloc_set_destructor(p1, NULL);
+
+ talloc_report(root, stderr);
+
+
+ p2 = (char *)talloc_zero_size(p1, 20);
+ torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
+ talloc_free(p2);
+
+ torture_assert("misc", talloc_strdup(root, NULL) == NULL,
+ "failed: strdup on NULL should give NULL\n");
+
+ p2 = talloc_strndup(p1, "foo", 2);
+ torture_assert("misc", strcmp("fo", p2) == 0,
+ "strndup doesn't work\n");
+ p2 = talloc_asprintf_append(p2, "o%c", 'd');
+ torture_assert("misc", strcmp("food", p2) == 0,
+ "talloc_asprintf_append doesn't work\n");
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 3);
+
+ p2 = talloc_asprintf_append(NULL, "hello %s", "world");
+ torture_assert("misc", strcmp("hello world", p2) == 0,
+ "talloc_asprintf_append doesn't work\n");
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 3);
+ talloc_free(p2);
+
+ d = talloc_array(p1, double, 0x20000000);
+ torture_assert("misc", !d, "failed: integer overflow not detected\n");
+
+ d = talloc_realloc(p1, d, double, 0x20000000);
+ torture_assert("misc", !d, "failed: integer overflow not detected\n");
+
+ talloc_free(p1);
+ CHECK_BLOCKS("misc", root, 1);
+
+ p1 = talloc_named(root, 100, "%d bytes", 100);
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+ talloc_unlink(root, p1);
+
+ p1 = talloc_init("%d bytes", 200);
+ p2 = talloc_asprintf(p1, "my test '%s'", "string");
+ torture_assert_str_equal("misc", p2, "my test 'string'",
+ "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
+ CHECK_BLOCKS("misc", p1, 3);
+ CHECK_SIZE("misc", p2, 17);
+ CHECK_BLOCKS("misc", root, 1);
+ talloc_unlink(NULL, p1);
+
+ p1 = talloc_named_const(root, 10, "p1");
+ p2 = (char *)talloc_named_const(root, 20, "p2");
+ (void)talloc_reference(p1, p2);
+ talloc_report_full(root, stderr);
+ talloc_unlink(root, p2);
+ talloc_report_full(root, stderr);
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 2);
+ CHECK_BLOCKS("misc", root, 3);
+ talloc_unlink(p1, p2);
+ talloc_unlink(root, p1);
+
+ p1 = talloc_named_const(root, 10, "p1");
+ p2 = (char *)talloc_named_const(root, 20, "p2");
+ (void)talloc_reference(NULL, p2);
+ talloc_report_full(root, stderr);
+ talloc_unlink(root, p2);
+ talloc_report_full(root, stderr);
+ CHECK_BLOCKS("misc", p2, 1);
+ CHECK_BLOCKS("misc", p1, 1);
+ CHECK_BLOCKS("misc", root, 2);
+ talloc_unlink(NULL, p2);
+ talloc_unlink(root, p1);
+
+ /* Test that talloc_unlink is a no-op */
+
+ torture_assert("misc", talloc_unlink(root, NULL) == -1,
+ "failed: talloc_unlink(root, NULL) == -1\n");
+
+ talloc_report(root, stderr);
+ talloc_report(NULL, stderr);
+
+ CHECK_SIZE("misc", root, 0);
+
+ talloc_free(root);
+
+ CHECK_SIZE("misc", NULL, 0);
+
+ talloc_enable_leak_report();
+ talloc_enable_leak_report_full();
+
+ printf("success: misc\n");
+
+ return true;
+}
+
+
+/*
+ test realloc
+*/
+static bool test_realloc(void)
+{
+ void *root, *p1, *p2;
+
+ printf("test: realloc [\nREALLOC\n]\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_size(root, 10);
+ CHECK_SIZE("realloc", p1, 10);
+
+ p1 = talloc_realloc_size(NULL, p1, 20);
+ CHECK_SIZE("realloc", p1, 20);
+
+ talloc_new(p1);
+
+ p2 = talloc_realloc_size(p1, NULL, 30);
+
+ talloc_new(p1);
+
+ p2 = talloc_realloc_size(p1, p2, 40);
+
+ CHECK_SIZE("realloc", p2, 40);
+ CHECK_SIZE("realloc", root, 60);
+ CHECK_BLOCKS("realloc", p1, 4);
+
+ p1 = talloc_realloc_size(NULL, p1, 20);
+ CHECK_SIZE("realloc", p1, 60);
+
+ talloc_increase_ref_count(p2);
+ torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
+ "failed: talloc_realloc() on a referenced pointer should fail\n");
+ CHECK_BLOCKS("realloc", p1, 4);
+
+ talloc_realloc_size(NULL, p2, 0);
+ talloc_realloc_size(NULL, p2, 0);
+ CHECK_BLOCKS("realloc", p1, 3);
+
+ torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
+ "failed: oversize talloc should fail\n");
+
+ talloc_realloc_size(NULL, p1, 0);
+
+ CHECK_BLOCKS("realloc", root, 1);
+ CHECK_SIZE("realloc", root, 0);
+
+ talloc_free(root);
+
+ printf("success: REALLOC\n");
+
+ return true;
+}
+
+/*
+ test realloc with a child
+*/
+static bool test_realloc_child(void)
+{
+ void *root;
+ struct el2 {
+ const char *name;
+ } *el2;
+ struct el1 {
+ int count;
+ struct el2 **list, **list2, **list3;
+ } *el1;
+
+ printf("test: REALLOC WITH CHILD\n");
+
+ root = talloc_new(NULL);
+
+ el1 = talloc(root, struct el1);
+ el1->list = talloc(el1, struct el2 *);
+ el1->list[0] = talloc(el1->list, struct el2);
+ el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
+
+ el1->list2 = talloc(el1, struct el2 *);
+ el1->list2[0] = talloc(el1->list2, struct el2);
+ el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
+
+ el1->list3 = talloc(el1, struct el2 *);
+ el1->list3[0] = talloc(el1->list3, struct el2);
+ el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
+
+ el2 = talloc(el1->list, struct el2);
+ el2 = talloc(el1->list2, struct el2);
+ el2 = talloc(el1->list3, struct el2);
+
+ el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
+ el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
+ el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
+
+ talloc_free(root);
+
+ printf("success: REALLOC WITH CHILD\n");
+ return true;
+}
+
+/*
+ test type checking
+*/
+static bool test_type(void)
+{
+ void *root;
+ struct el1 {
+ int count;
+ };
+ struct el2 {
+ int count;
+ };
+ struct el1 *el1;
+
+ printf("test: type [\ntalloc type checking\n]\n");
+
+ root = talloc_new(NULL);
+
+ el1 = talloc(root, struct el1);
+
+ el1->count = 1;
+
+ torture_assert("type", talloc_get_type(el1, struct el1) == el1,
+ "type check failed on el1\n");
+ torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
+ "type check failed on el1 with el2\n");
+ talloc_set_type(el1, struct el2);
+ torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
+ "type set failed on el1 with el2\n");
+
+ talloc_free(root);
+
+ printf("success: type\n");
+ return true;
+}
+
+/*
+ test steal
+*/
+static bool test_steal(void)
+{
+ void *root, *p1, *p2;
+
+ printf("test: steal [\nSTEAL\n]\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_array(root, char, 10);
+ CHECK_SIZE("steal", p1, 10);
+
+ p2 = talloc_realloc(root, NULL, char, 20);
+ CHECK_SIZE("steal", p1, 10);
+ CHECK_SIZE("steal", root, 30);
+
+ torture_assert("steal", talloc_steal(p1, NULL) == NULL,
+ "failed: stealing NULL should give NULL\n");
+
+ torture_assert("steal", talloc_steal(p1, p1) == p1,
+ "failed: stealing to ourselves is a nop\n");
+ CHECK_BLOCKS("steal", root, 3);
+ CHECK_SIZE("steal", root, 30);
+
+ talloc_steal(NULL, p1);
+ talloc_steal(NULL, p2);
+ CHECK_BLOCKS("steal", root, 1);
+ CHECK_SIZE("steal", root, 0);
+
+ talloc_free(p1);
+ talloc_steal(root, p2);
+ CHECK_BLOCKS("steal", root, 2);
+ CHECK_SIZE("steal", root, 20);
+
+ talloc_free(p2);
+
+ CHECK_BLOCKS("steal", root, 1);
+ CHECK_SIZE("steal", root, 0);
+
+ talloc_free(root);
+
+ p1 = talloc_size(NULL, 3);
+ talloc_report_full(NULL, stderr);
+ CHECK_SIZE("steal", NULL, 3);
+ talloc_free(p1);
+
+ printf("success: steal\n");
+ return true;
+}
+
+/*
+ test move
+*/
+static bool test_move(void)
+{
+ void *root;
+ struct t_move {
+ char *p;
+ int *x;
+ } *t1, *t2;
+
+ printf("test: move [\nMOVE\n]\n");
+
+ root = talloc_new(NULL);
+
+ t1 = talloc(root, struct t_move);
+ t2 = talloc(root, struct t_move);
+ t1->p = talloc_strdup(t1, "foo");
+ t1->x = talloc(t1, int);
+ *t1->x = 42;
+
+ t2->p = talloc_move(t2, &t1->p);
+ t2->x = talloc_move(t2, &t1->x);
+ torture_assert("move", t1->p == NULL && t1->x == NULL &&
+ strcmp(t2->p, "foo") == 0 && *t2->x == 42,
+ "talloc move failed");
+
+ talloc_free(root);
+
+ printf("success: move\n");
+
+ return true;
+}
+
+/*
+ test talloc_realloc_fn
+*/
+static bool test_realloc_fn(void)
+{
+ void *root, *p1;
+
+ printf("test: realloc_fn [\ntalloc_realloc_fn\n]\n");
+
+ root = talloc_new(NULL);
+
+ p1 = talloc_realloc_fn(root, NULL, 10);
+ CHECK_BLOCKS("realloc_fn", root, 2);
+ CHECK_SIZE("realloc_fn", root, 10);
+ p1 = talloc_realloc_fn(root, p1, 20);
+ CHECK_BLOCKS("realloc_fn", root, 2);
+ CHECK_SIZE("realloc_fn", root, 20);
+ p1 = talloc_realloc_fn(root, p1, 0);
+ CHECK_BLOCKS("realloc_fn", root, 1);
+ CHECK_SIZE("realloc_fn", root, 0);
+
+ talloc_free(root);
+
+ printf("success: realloc_fn\n");
+ return true;
+}
+
+
+static bool test_unref_reparent(void)
+{
+ void *root, *p1, *p2, *c1;
+
+ printf("test: unref_reparent [\nUNREFERENCE AFTER PARENT FREED\n]\n");
+
+ root = talloc_named_const(NULL, 0, "root");
+ p1 = talloc_named_const(root, 1, "orig parent");
+ p2 = talloc_named_const(root, 1, "parent by reference");
+
+ c1 = talloc_named_const(p1, 1, "child");
+ talloc_reference(p2, c1);
+
+ CHECK_PARENT("unref_reparent", c1, p1);
+
+ talloc_free(p1);
+
+ CHECK_PARENT("unref_reparent", c1, p2);
+
+ talloc_unlink(p2, c1);
+
+ CHECK_SIZE("unref_reparent", root, 1);
+
+ talloc_free(p2);
+ talloc_free(root);
+
+ printf("success: unref_reparent\n");
+ return true;
+}
+
+/*
+ measure the speed of talloc versus malloc
+*/
+static bool test_speed(void)
+{
+ void *ctx = talloc_new(NULL);
+ unsigned count;
+ const int loop = 1000;
+ int i;
+ struct timeval tv;
+
+ printf("test: speed [\nTALLOC VS MALLOC SPEED\n]\n");
+
+ tv = timeval_current();
+ count = 0;
+ do {
+ void *p1, *p2, *p3;
+ for (i=0;i<loop;i++) {
+ p1 = talloc_size(ctx, loop % 100);
+ p2 = talloc_strdup(p1, "foo bar");
+ p3 = talloc_size(p1, 300);
+ talloc_free(p1);
+ }
+ count += 3 * loop;
+ } while (timeval_elapsed(&tv) < 5.0);
+
+ fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+
+ talloc_free(ctx);
+
+ tv = timeval_current();
+ count = 0;
+ do {
+ void *p1, *p2, *p3;
+ for (i=0;i<loop;i++) {
+ p1 = malloc(loop % 100);
+ p2 = strdup("foo bar");
+ p3 = malloc(300);
+ free(p1);
+ free(p2);
+ free(p3);
+ }
+ count += 3 * loop;
+ } while (timeval_elapsed(&tv) < 5.0);
+ fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+
+ printf("success: speed\n");
+
+ return true;
+}
+
+static bool test_lifeless(void)
+{
+ void *top = talloc_new(NULL);
+ char *parent, *child;
+ void *child_owner = talloc_new(NULL);
+
+ printf("test: lifeless [\nTALLOC_UNLINK LOOP\n]\n");
+
+ parent = talloc_strdup(top, "parent");
+ child = talloc_strdup(parent, "child");
+ (void)talloc_reference(child, parent);
+ (void)talloc_reference(child_owner, child);
+ talloc_report_full(top, stderr);
+ talloc_unlink(top, parent);
+ talloc_free(child);
+ talloc_report_full(top, stderr);
+ talloc_free(top);
+ talloc_free(child_owner);
+ talloc_free(child);
+
+ printf("success: lifeless\n");
+ return true;
+}
+
+static int loop_destructor_count;
+
+static int test_loop_destructor(char *ptr)
+{
+ loop_destructor_count++;
+ return 0;
+}
+
+static bool test_loop(void)
+{
+ void *top = talloc_new(NULL);
+ char *parent;
+ struct req1 {
+ char *req2, *req3;
+ } *req1;
+
+ printf("test: loop [\nTALLOC LOOP DESTRUCTION\n]\n");
+
+ parent = talloc_strdup(top, "parent");
+ req1 = talloc(parent, struct req1);
+ req1->req2 = talloc_strdup(req1, "req2");
+ talloc_set_destructor(req1->req2, test_loop_destructor);
+ req1->req3 = talloc_strdup(req1, "req3");
+ (void)talloc_reference(req1->req3, req1);
+ talloc_report_full(top, stderr);
+ talloc_free(parent);
+ talloc_report_full(top, stderr);
+ talloc_report_full(NULL, stderr);
+ talloc_free(top);
+
+ torture_assert("loop", loop_destructor_count == 1,
+ "FAILED TO FIRE LOOP DESTRUCTOR\n");
+ loop_destructor_count = 0;
+
+ printf("success: loop\n");
+ return true;
+}
+
+static int fail_destructor_str(char *ptr)
+{
+ return -1;
+}
+
+static bool test_free_parent_deny_child(void)
+{
+ void *top = talloc_new(NULL);
+ char *level1;
+ char *level2;
+ char *level3;
+
+ printf("test: free_parent_deny_child [\nTALLOC FREE PARENT DENY CHILD\n]\n");
+
+ level1 = talloc_strdup(top, "level1");
+ level2 = talloc_strdup(level1, "level2");
+ level3 = talloc_strdup(level2, "level3");
+
+ talloc_set_destructor(level3, fail_destructor_str);
+ talloc_free(level1);
+ talloc_set_destructor(level3, NULL);
+
+ CHECK_PARENT("free_parent_deny_child", level3, top);
+
+ talloc_free(top);
+
+ printf("success: free_parent_deny_child\n");
+ return true;
+}
+
+static bool test_talloc_ptrtype(void)
+{
+ void *top = talloc_new(NULL);
+ struct struct1 {
+ int foo;
+ int bar;
+ } *s1, *s2, **s3, ***s4;
+ const char *location1;
+ const char *location2;
+ const char *location3;
+ const char *location4;
+
+ printf("test: ptrtype [\nTALLOC PTRTYPE\n]\n");
+
+ s1 = talloc_ptrtype(top, s1);location1 = __location__;
+
+ if (talloc_get_size(s1) != sizeof(struct struct1)) {
+ printf("failure: ptrtype [\n"
+ "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
+ "]\n", (unsigned long)talloc_get_size(s1),
+ (unsigned long)sizeof(struct struct1));
+ return false;
+ }
+
+ if (strcmp(location1, talloc_get_name(s1)) != 0) {
+ printf("failure: ptrtype [\n"
+ "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
+ talloc_get_name(s1), location1);
+ return false;
+ }
+
+ s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
+
+ if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s2),
+ (unsigned long)(sizeof(struct struct1)*10));
+ return false;
+ }
+
+ if (strcmp(location2, talloc_get_name(s2)) != 0) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
+ talloc_get_name(s2), location2);
+ return false;
+ }
+
+ s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
+
+ if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
+ printf("failure: ptrtype [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s3),
+ (unsigned long)(sizeof(struct struct1 *)*10));
+ return false;
+ }
+
+ torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
+ "talloc_array_ptrtype() sets the wrong name");
+
+ s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
+
+ if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
+ printf("failure: TALLOC PTRTYPE [\n"
+ "talloc_array_ptrtype() allocated the wrong size "
+ "%lu (should be %lu)\n]\n",
+ (unsigned long)talloc_get_size(s4),
+ (unsigned long)(sizeof(struct struct1 **)*10));
+ return false;
+ }
+
+ torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
+ "talloc_array_ptrtype() sets the wrong name");
+
+ talloc_free(top);
+
+ printf("success: ptrtype\n");
+ return true;
+}
+
+static bool test_autofree(void)
+{
+ void *p;
+ printf("test: autofree [\nTALLOC AUTOFREE CONTEXT\n]\n");
+
+ p = talloc_autofree_context();
+ talloc_free(p);
+
+ p = talloc_autofree_context();
+ talloc_free(p);
+
+ printf("success: autofree\n");
+ return true;
+}
+
+int main(void)
+{
+ bool ret = true;
+
+ talloc_disable_null_tracking();
+ talloc_enable_null_tracking();
+
+ ret &= test_ref1();
+ ret &= test_ref2();
+ ret &= test_ref3();
+ ret &= test_ref4();
+ ret &= test_unlink1();
+ ret &= test_misc();
+ ret &= test_realloc();
+ ret &= test_realloc_child();
+ ret &= test_steal();
+ ret &= test_move();
+ ret &= test_unref_reparent();
+ ret &= test_realloc_fn();
+ ret &= test_type();
+ ret &= test_lifeless();
+ ret &= test_loop();
+ ret &= test_free_parent_deny_child();
+ ret &= test_talloc_ptrtype();
+
+ if (ret) {
+ ret &= test_speed();
+ }
+ ret &= test_autofree();
+
+ if (!ret)
+ return -1;
+ return 0;
+}
diff --git a/source/lib/talloc/web/index.html b/source/lib/talloc/web/index.html
new file mode 100644
index 00000000000..106920e8a59
--- /dev/null
+++ b/source/lib/talloc/web/index.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>talloc</TITLE>
+</HEAD>
+<BODY BGCOLOR="#ffffff" TEXT="#000000" VLINK="#292555" LINK="#292555" ALINK="#cc0033">
+
+<h1>talloc</h1>
+
+talloc is a hierarchical pool based memory allocator with
+destructors. It is the core memory allocator used in Samba4, and has
+made a huge difference in many aspects of Samba4 development.<p>
+
+To get started with talloc, I would recommend you read the <a
+href="http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt">talloc guide</a>.
+
+<h2>Discussion and bug reports</h2>
+
+talloc does not currently have its own mailing list or bug tracking
+system. For now, please use the <a
+href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a>
+mailing list, and the <a href="http://bugzilla.samba.org/">Samba
+bugzilla</a> bug tracking system.
+
+<h2>Download</h2>
+
+You can download the latest release either via rsync or anonymous
+svn. To fetch via svn use the following command:
+
+<pre>
+ svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc
+ svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/replace libreplace
+</pre>
+
+To fetch via rsync use this command:
+
+<pre>
+ rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc .
+ rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/libreplace .
+</pre>
+
+<hr>
+<tiny>
+<a href="http://samba.org/~tridge/">Andrew Tridgell</a><br>
+talloc AT tridgell.net
+</tiny>
+
+</BODY>
+</HTML>
diff --git a/source/lib/tallocmsg.c b/source/lib/tallocmsg.c
index b515093cd69..0f493538f3c 100644
--- a/source/lib/tallocmsg.c
+++ b/source/lib/tallocmsg.c
@@ -25,31 +25,75 @@
* Glue code between talloc profiling and the Samba messaging system.
**/
+struct msg_pool_usage_state {
+ TALLOC_CTX *mem_ctx;
+ ssize_t len;
+ size_t buflen;
+ char *s;
+};
+
+static void msg_pool_usage_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_s)
+{
+ const char *name = talloc_get_name(ptr);
+ struct msg_pool_usage_state *state = (struct msg_pool_usage_state *)_s;
+
+ if (is_ref) {
+ sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
+ "%*sreference to: %s\n", depth*4, "", name);
+ return;
+ }
+
+ if (depth == 0) {
+ sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
+ "%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
+ (max_depth < 0 ? "full " :""), name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+ return;
+ }
+
+ sprintf_append(state->mem_ctx, &state->s, &state->len, &state->buflen,
+ "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
+ depth*4, "",
+ name,
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr),
+ talloc_reference_count(ptr));
+}
/**
* Respond to a POOL_USAGE message by sending back string form of memory
* usage stats.
**/
void msg_pool_usage(int msg_type, struct process_id src_pid,
- void *UNUSED(buf), size_t UNUSED(len))
+ void *UNUSED(buf), size_t UNUSED(len),
+ void *private_data)
{
- char *reply = NULL;
+ struct msg_pool_usage_state state;
SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE);
DEBUG(2,("Got POOL_USAGE\n"));
- reply = talloc_describe_all();
- if (!reply) {
+ state.mem_ctx = talloc_init("msg_pool_usage");
+ if (!state.mem_ctx) {
+ return;
+ }
+ state.len = 0;
+ state.buflen = 512;
+ state.s = NULL;
+
+ talloc_report_depth_cb(NULL, 0, -1, msg_pool_usage_helper, &state);
+
+ if (!state.s) {
+ talloc_destroy(state.mem_ctx);
return;
}
- become_root();
message_send_pid(src_pid, MSG_POOL_USAGE,
- reply, strlen(reply)+1, True);
- unbecome_root();
+ state.s, strlen(state.s)+1, True);
- SAFE_FREE(reply);
+ talloc_destroy(state.mem_ctx);
}
/**
@@ -57,6 +101,6 @@ void msg_pool_usage(int msg_type, struct process_id src_pid,
**/
void register_msg_pool_usage(void)
{
- message_register(MSG_REQ_POOL_USAGE, msg_pool_usage);
+ message_register(MSG_REQ_POOL_USAGE, msg_pool_usage, NULL);
DEBUG(2, ("Registered MSG_REQ_POOL_USAGE\n"));
}
diff --git a/source/lib/talloctort.c b/source/lib/talloctort.c
deleted file mode 100644
index 6504203a7ad..00000000000
--- a/source/lib/talloctort.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- local testing of talloc routines.
-
- Copyright (C) Andrew Tridgell 2004
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifdef _SAMBA_BUILD_
-#include "includes.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <sys/time.h>
-#include <time.h>
-#include "talloc.h"
-#endif
-
-/* the test suite can be built standalone, or as part of Samba */
-#ifndef _SAMBA_BUILD_
-typedef enum {False=0,True=1} BOOL;
-#endif
-
-/* Samba3 does not define the timeval functions below */
-#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
-
-static double timeval_elapsed(struct timeval *tv)
-{
- struct timeval tv2 = timeval_current();
- return (tv2.tv_sec - tv->tv_sec) +
- (tv2.tv_usec - tv->tv_usec)*1.0e-6;
-}
-#endif /* _SAMBA_BUILD_ */
-
-#if SAMBA_VERSION_MAJOR<4
-#ifdef malloc
-#undef malloc
-#endif
-#ifdef strdup
-#undef strdup
-#endif
-#endif
-
-#define CHECK_SIZE(ptr, tsize) do { \
- if (talloc_total_size(ptr) != (tsize)) { \
- printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \
- #ptr, \
- (unsigned)talloc_total_size(ptr), \
- (unsigned)tsize); \
- talloc_report_full(ptr, stdout); \
- return False; \
- } \
-} while (0)
-
-#define CHECK_BLOCKS(ptr, tblocks) do { \
- if (talloc_total_blocks(ptr) != (tblocks)) { \
- printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \
- #ptr, \
- (unsigned)talloc_total_blocks(ptr), \
- (unsigned)tblocks); \
- talloc_report_full(ptr, stdout); \
- return False; \
- } \
-} while (0)
-
-
-/*
- test references
-*/
-static BOOL test_ref1(void)
-{
- void *root, *p1, *p2, *ref, *r1;
-
- printf("TESTING SINGLE REFERENCE FREE\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "p1");
- p2 = talloc_named_const(p1, 1, "p2");
- talloc_named_const(p1, 1, "x1");
- talloc_named_const(p1, 2, "x2");
- talloc_named_const(p1, 3, "x3");
-
- r1 = talloc_named_const(root, 1, "r1");
- ref = talloc_reference(r1, p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 2);
-
- printf("Freeing p2\n");
- talloc_free(p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p1\n");
- talloc_free(p1);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing r1\n");
- talloc_free(r1);
- talloc_report_full(NULL, stdout);
-
- printf("Testing NULL\n");
- if (talloc_reference(root, NULL)) {
- return False;
- }
-
- CHECK_BLOCKS(root, 1);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-/*
- test references
-*/
-static BOOL test_ref2(void)
-{
- void *root, *p1, *p2, *ref, *r1;
-
- printf("TESTING DOUBLE REFERENCE FREE\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "p1");
- talloc_named_const(p1, 1, "x1");
- talloc_named_const(p1, 1, "x2");
- talloc_named_const(p1, 1, "x3");
- p2 = talloc_named_const(p1, 1, "p2");
-
- r1 = talloc_named_const(root, 1, "r1");
- ref = talloc_reference(r1, p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 2);
-
- printf("Freeing ref\n");
- talloc_free(ref);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p2\n");
- talloc_free(p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 4);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p1\n");
- talloc_free(p1);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing r1\n");
- talloc_free(r1);
- talloc_report_full(root, stdout);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-/*
- test references
-*/
-static BOOL test_ref3(void)
-{
- void *root, *p1, *p2, *ref, *r1;
-
- printf("TESTING PARENT REFERENCE FREE\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "p1");
- p2 = talloc_named_const(root, 1, "p2");
- r1 = talloc_named_const(p1, 1, "r1");
- ref = talloc_reference(p2, r1);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 2);
- CHECK_BLOCKS(p2, 2);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p1\n");
- talloc_free(p1);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p2, 2);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p2\n");
- talloc_free(p2);
- talloc_report_full(root, stdout);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-/*
- test references
-*/
-static BOOL test_ref4(void)
-{
- void *root, *p1, *p2, *ref, *r1;
-
- printf("TESTING REFERRER REFERENCE FREE\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "p1");
- talloc_named_const(p1, 1, "x1");
- talloc_named_const(p1, 1, "x2");
- talloc_named_const(p1, 1, "x3");
- p2 = talloc_named_const(p1, 1, "p2");
-
- r1 = talloc_named_const(root, 1, "r1");
- ref = talloc_reference(r1, p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 2);
-
- printf("Freeing r1\n");
- talloc_free(r1);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 5);
- CHECK_BLOCKS(p2, 1);
-
- printf("Freeing p2\n");
- talloc_free(p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 4);
-
- printf("Freeing p1\n");
- talloc_free(p1);
- talloc_report_full(root, stdout);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-
-/*
- test references
-*/
-static BOOL test_unlink1(void)
-{
- void *root, *p1, *p2, *ref, *r1;
-
- printf("TESTING UNLINK\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "p1");
- talloc_named_const(p1, 1, "x1");
- talloc_named_const(p1, 1, "x2");
- talloc_named_const(p1, 1, "x3");
- p2 = talloc_named_const(p1, 1, "p2");
-
- r1 = talloc_named_const(p1, 1, "r1");
- ref = talloc_reference(r1, p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 7);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 2);
-
- printf("Unreferencing r1\n");
- talloc_unlink(r1, p2);
- talloc_report_full(root, stdout);
-
- CHECK_BLOCKS(p1, 6);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(r1, 1);
-
- printf("Freeing p1\n");
- talloc_free(p1);
- talloc_report_full(root, stdout);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-static int fail_destructor(void *ptr)
-{
- return -1;
-}
-
-/*
- miscellaneous tests to try to get a higher test coverage percentage
-*/
-static BOOL test_misc(void)
-{
- void *root, *p1;
- char *p2;
- double *d;
-
- printf("TESTING MISCELLANEOUS\n");
-
- root = talloc_new(NULL);
-
- p1 = talloc_size(root, 0x7fffffff);
- if (p1) {
- printf("failed: large talloc allowed\n");
- return False;
- }
-
- p1 = talloc_strdup(root, "foo");
- talloc_increase_ref_count(p1);
- talloc_increase_ref_count(p1);
- talloc_increase_ref_count(p1);
- CHECK_BLOCKS(p1, 1);
- CHECK_BLOCKS(root, 2);
- talloc_free(p1);
- CHECK_BLOCKS(p1, 1);
- CHECK_BLOCKS(root, 2);
- talloc_unlink(NULL, p1);
- CHECK_BLOCKS(p1, 1);
- CHECK_BLOCKS(root, 2);
- p2 = talloc_strdup(p1, "foo");
- if (talloc_unlink(root, p2) != -1) {
- printf("failed: talloc_unlink() of non-reference context should return -1\n");
- return False;
- }
- if (talloc_unlink(p1, p2) != 0) {
- printf("failed: talloc_unlink() of parent should succeed\n");
- return False;
- }
- talloc_free(p1);
- CHECK_BLOCKS(p1, 1);
- CHECK_BLOCKS(root, 2);
-
- talloc_set_name(p1, "my name is %s", "foo");
- if (strcmp(talloc_get_name(p1), "my name is foo") != 0) {
- printf("failed: wrong name after talloc_set_name\n");
- return False;
- }
- CHECK_BLOCKS(p1, 2);
- CHECK_BLOCKS(root, 3);
-
- talloc_set_name_const(p1, NULL);
- if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) {
- printf("failed: wrong name after talloc_set_name(NULL)\n");
- return False;
- }
- CHECK_BLOCKS(p1, 2);
- CHECK_BLOCKS(root, 3);
-
-
- if (talloc_free(NULL) != -1) {
- printf("talloc_free(NULL) should give -1\n");
- return False;
- }
-
- talloc_set_destructor(p1, fail_destructor);
- if (talloc_free(p1) != -1) {
- printf("Failed destructor should cause talloc_free to fail\n");
- return False;
- }
- talloc_set_destructor(p1, NULL);
-
- talloc_report(root, stdout);
-
-
- p2 = talloc_zero_size(p1, 20);
- if (p2[19] != 0) {
- printf("Failed to give zero memory\n");
- return False;
- }
- talloc_free(p2);
-
- if (talloc_strdup(root, NULL) != NULL) {
- printf("failed: strdup on NULL should give NULL\n");
- return False;
- }
-
- p2 = talloc_strndup(p1, "foo", 2);
- if (strcmp("fo", p2) != 0) {
- printf("failed: strndup doesn't work\n");
- return False;
- }
- p2 = talloc_asprintf_append(p2, "o%c", 'd');
- if (strcmp("food", p2) != 0) {
- printf("failed: talloc_asprintf_append doesn't work\n");
- return False;
- }
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(p1, 3);
-
- p2 = talloc_asprintf_append(NULL, "hello %s", "world");
- if (strcmp("hello world", p2) != 0) {
- printf("failed: talloc_asprintf_append doesn't work\n");
- return False;
- }
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(p1, 3);
- talloc_free(p2);
-
- d = talloc_array(p1, double, 0x20000000);
- if (d) {
- printf("failed: integer overflow not detected\n");
- return False;
- }
-
- d = talloc_realloc(p1, d, double, 0x20000000);
- if (d) {
- printf("failed: integer overflow not detected\n");
- return False;
- }
-
- talloc_free(p1);
- CHECK_BLOCKS(root, 1);
-
- p1 = talloc_named(root, 100, "%d bytes", 100);
- CHECK_BLOCKS(p1, 2);
- CHECK_BLOCKS(root, 3);
- talloc_unlink(root, p1);
-
- p1 = talloc_init("%d bytes", 200);
- p2 = talloc_asprintf(p1, "my test '%s'", "string");
- CHECK_BLOCKS(p1, 3);
- CHECK_SIZE(p2, 17);
- CHECK_BLOCKS(root, 1);
- talloc_unlink(NULL, p1);
-
- p1 = talloc_named_const(root, 10, "p1");
- p2 = talloc_named_const(root, 20, "p2");
- talloc_reference(p1, p2);
- talloc_report_full(root, stdout);
- talloc_unlink(root, p2);
- talloc_report_full(root, stdout);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(p1, 2);
- CHECK_BLOCKS(root, 3);
- talloc_unlink(p1, p2);
- talloc_unlink(root, p1);
-
- p1 = talloc_named_const(root, 10, "p1");
- p2 = talloc_named_const(root, 20, "p2");
- talloc_reference(NULL, p2);
- talloc_report_full(root, stdout);
- talloc_unlink(root, p2);
- talloc_report_full(root, stdout);
- CHECK_BLOCKS(p2, 1);
- CHECK_BLOCKS(p1, 1);
- CHECK_BLOCKS(root, 2);
- talloc_unlink(NULL, p2);
- talloc_unlink(root, p1);
-
- /* Test that talloc_unlink is a no-op */
-
- if (talloc_unlink(root, NULL) != -1) {
- printf("failed: talloc_unlink(root, NULL) == -1\n");
- return False;
- }
-
- talloc_report(root, stdout);
- talloc_report(NULL, stdout);
-
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- CHECK_SIZE(NULL, 0);
-
- talloc_enable_leak_report();
- talloc_enable_leak_report_full();
-
- return True;
-}
-
-
-/*
- test realloc
-*/
-static BOOL test_realloc(void)
-{
- void *root, *p1, *p2;
-
- printf("TESTING REALLOC\n");
-
- root = talloc_new(NULL);
-
- p1 = talloc_size(root, 10);
- CHECK_SIZE(p1, 10);
-
- p1 = talloc_realloc_size(NULL, p1, 20);
- CHECK_SIZE(p1, 20);
-
- talloc_new(p1);
-
- p2 = talloc_realloc_size(p1, NULL, 30);
-
- talloc_new(p1);
-
- p2 = talloc_realloc_size(p1, p2, 40);
-
- CHECK_SIZE(p2, 40);
- CHECK_SIZE(root, 60);
- CHECK_BLOCKS(p1, 4);
-
- p1 = talloc_realloc_size(NULL, p1, 20);
- CHECK_SIZE(p1, 60);
-
- talloc_increase_ref_count(p2);
- if (talloc_realloc_size(NULL, p2, 5) != NULL) {
- printf("failed: talloc_realloc() on a referenced pointer should fail\n");
- return False;
- }
- CHECK_BLOCKS(p1, 4);
-
- talloc_realloc_size(NULL, p2, 0);
- talloc_realloc_size(NULL, p2, 0);
- CHECK_BLOCKS(p1, 3);
-
- if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) {
- printf("failed: oversize talloc should fail\n");
- return False;
- }
-
- talloc_realloc_size(NULL, p1, 0);
-
- CHECK_BLOCKS(root, 1);
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- return True;
-}
-
-
-/*
- test realloc with a child
-*/
-static BOOL test_realloc_child(void)
-{
- void *root;
- struct el1 {
- int count;
- struct el2 {
- const char *name;
- } **list, **list2, **list3;
- } *el1;
- struct el2 *el2;
-
- printf("TESTING REALLOC WITH CHILD\n");
-
- root = talloc_new(NULL);
-
- el1 = talloc(root, struct el1);
- el1->list = talloc(el1, struct el2 *);
- el1->list[0] = talloc(el1->list, struct el2);
- el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
-
- el1->list2 = talloc(el1, struct el2 *);
- el1->list2[0] = talloc(el1->list2, struct el2);
- el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
-
- el1->list3 = talloc(el1, struct el2 *);
- el1->list3[0] = talloc(el1->list3, struct el2);
- el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
-
- el2 = talloc(el1->list, struct el2);
- el2 = talloc(el1->list2, struct el2);
- el2 = talloc(el1->list3, struct el2);
-
- el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
- el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
- el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
-
- talloc_free(root);
-
- return True;
-}
-
-
-/*
- test type checking
-*/
-static BOOL test_type(void)
-{
- void *root;
- struct el1 {
- int count;
- };
- struct el2 {
- int count;
- };
- struct el1 *el1;
-
- printf("TESTING talloc type checking\n");
-
- root = talloc_new(NULL);
-
- el1 = talloc(root, struct el1);
-
- el1->count = 1;
-
- if (talloc_get_type(el1, struct el1) != el1) {
- printf("type check failed on el1\n");
- return False;
- }
- if (talloc_get_type(el1, struct el2) != NULL) {
- printf("type check failed on el1 with el2\n");
- return False;
- }
- talloc_set_type(el1, struct el2);
- if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) {
- printf("type set failed on el1 with el2\n");
- return False;
- }
-
- talloc_free(root);
-
- return True;
-}
-
-/*
- test steal
-*/
-static BOOL test_steal(void)
-{
- void *root, *p1, *p2;
-
- printf("TESTING STEAL\n");
-
- root = talloc_new(NULL);
-
- p1 = talloc_array(root, char, 10);
- CHECK_SIZE(p1, 10);
-
- p2 = talloc_realloc(root, NULL, char, 20);
- CHECK_SIZE(p1, 10);
- CHECK_SIZE(root, 30);
-
- if (talloc_steal(p1, NULL) != NULL) {
- printf("failed: stealing NULL should give NULL\n");
- return False;
- }
-
- if (talloc_steal(p1, p1) != p1) {
- printf("failed: stealing to ourselves is a nop\n");
- return False;
- }
- CHECK_BLOCKS(root, 3);
- CHECK_SIZE(root, 30);
-
- talloc_steal(NULL, p1);
- talloc_steal(NULL, p2);
- CHECK_BLOCKS(root, 1);
- CHECK_SIZE(root, 0);
-
- talloc_free(p1);
- talloc_steal(root, p2);
- CHECK_BLOCKS(root, 2);
- CHECK_SIZE(root, 20);
-
- talloc_free(p2);
-
- CHECK_BLOCKS(root, 1);
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
- p1 = talloc_size(NULL, 3);
- CHECK_SIZE(NULL, 3);
- talloc_free(p1);
-
- return True;
-}
-
-/*
- test talloc_realloc_fn
-*/
-static BOOL test_realloc_fn(void)
-{
- void *root, *p1;
-
- printf("TESTING talloc_realloc_fn\n");
-
- root = talloc_new(NULL);
-
- p1 = talloc_realloc_fn(root, NULL, 10);
- CHECK_BLOCKS(root, 2);
- CHECK_SIZE(root, 10);
- p1 = talloc_realloc_fn(root, p1, 20);
- CHECK_BLOCKS(root, 2);
- CHECK_SIZE(root, 20);
- p1 = talloc_realloc_fn(root, p1, 0);
- CHECK_BLOCKS(root, 1);
- CHECK_SIZE(root, 0);
-
- talloc_free(root);
-
-
- return True;
-}
-
-
-static BOOL test_unref_reparent(void)
-{
- void *root, *p1, *p2, *c1;
-
- printf("TESTING UNREFERENCE AFTER PARENT FREED\n");
-
- root = talloc_named_const(NULL, 0, "root");
- p1 = talloc_named_const(root, 1, "orig parent");
- p2 = talloc_named_const(root, 1, "parent by reference");
-
- c1 = talloc_named_const(p1, 1, "child");
- talloc_reference(p2, c1);
-
- talloc_free(p1);
- talloc_unlink(p2, c1);
-
- CHECK_SIZE(root, 1);
-
- talloc_free(p2);
- talloc_free(root);
-
- return True;
-}
-
-/*
- measure the speed of talloc versus malloc
-*/
-static BOOL test_speed(void)
-{
- void *ctx = talloc_new(NULL);
- unsigned count;
- struct timeval tv;
-
- printf("MEASURING TALLOC VS MALLOC SPEED\n");
-
- tv = timeval_current();
- count = 0;
- do {
- void *p1, *p2, *p3;
- p1 = talloc_size(ctx, count);
- p2 = talloc_strdup(p1, "foo bar");
- p3 = talloc_size(p1, 300);
- talloc_free(p1);
- count += 3;
- } while (timeval_elapsed(&tv) < 5.0);
-
- printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
-
- talloc_free(ctx);
-
- tv = timeval_current();
- count = 0;
- do {
- void *p1, *p2, *p3;
- p1 = malloc(count);
- p2 = strdup("foo bar");
- p3 = malloc(300);
- free(p1);
- free(p2);
- free(p3);
- count += 3;
- } while (timeval_elapsed(&tv) < 5.0);
-
- printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
-
- return True;
-}
-
-
-BOOL torture_local_talloc(void)
-{
- BOOL ret = True;
-
- ret &= test_ref1();
- ret &= test_ref2();
- ret &= test_ref3();
- ret &= test_ref4();
- ret &= test_unlink1();
- ret &= test_misc();
- ret &= test_realloc();
- ret &= test_realloc_child();
- ret &= test_steal();
- ret &= test_unref_reparent();
- ret &= test_realloc_fn();
- ret &= test_type();
- if (ret) {
- ret &= test_speed();
- }
-
- return ret;
-}
-
-
-
-#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
- int main(void)
-{
- if (!torture_local_talloc()) {
- printf("ERROR: TESTSUIE FAILED\n");
- return -1;
- }
- return 0;
-}
-#endif
diff --git a/source/lib/time.c b/source/lib/time.c
index 9a539d415e8..403fb0594d4 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -1,8 +1,10 @@
/*
Unix SMB/CIFS implementation.
time handling functions
- Copyright (C) Andrew Tridgell 1992-1998
+
+ Copyright (C) Andrew Tridgell 1992-2004
Copyright (C) Stefan (metze) Metzmacher 2002
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -20,16 +22,11 @@
#include "includes.h"
-/*
- This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com>
- in May 1996
- */
+/**
+ * @file
+ * @brief time handling functions
+ */
-int extra_time_offset = 0;
-
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
#ifndef TIME_T_MIN
#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
@@ -39,19 +36,17 @@ int extra_time_offset = 0;
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
-/*******************************************************************
+/**
External access to time_t_min and time_t_max.
-********************************************************************/
-
+**/
time_t get_time_t_max(void)
{
return TIME_T_MAX;
}
-/*******************************************************************
- A gettimeofday wrapper.
-********************************************************************/
-
+/**
+a gettimeofday wrapper
+**/
void GetTimeOfDay(struct timeval *tval)
{
#ifdef HAVE_GETTIMEOFDAY_TZ
@@ -61,220 +56,35 @@ void GetTimeOfDay(struct timeval *tval)
#endif
}
-#define TM_YEAR_BASE 1900
-
-/*******************************************************************
- Yield the difference between *A and *B, in seconds, ignoring leap seconds.
-********************************************************************/
-
-static int tm_diff(struct tm *a, struct tm *b)
-{
- int ay = a->tm_year + (TM_YEAR_BASE - 1);
- int by = b->tm_year + (TM_YEAR_BASE - 1);
- int intervening_leap_days = (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
- int years = ay - by;
- int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
- int hours = 24*days + (a->tm_hour - b->tm_hour);
- int minutes = 60*hours + (a->tm_min - b->tm_min);
- int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
-
- return seconds;
-}
-
-/*******************************************************************
- Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
-******************************************************************/
-
-int get_time_zone(time_t t)
-{
- struct tm *tm = gmtime(&t);
- struct tm tm_utc;
-
- if (!tm) {
- return 0;
- }
- tm_utc = *tm;
- tm = localtime(&t);
- if (!tm) {
- return 0;
- }
- return tm_diff(&tm_utc,tm) + 60*extra_time_offset;
-}
-
-/*******************************************************************
- Accessor function for the server time zone offset.
- set_server_zone_offset() must have been called first.
-******************************************************************/
-
-static int server_zone_offset;
-
-int get_server_zone_offset(void)
-{
- return server_zone_offset;
-}
-
-/*******************************************************************
- Initialize the server time zone offset. Called when a client connects.
-******************************************************************/
-
-int set_server_zone_offset(time_t t)
+struct timespec convert_time_t_to_timespec(time_t t)
{
- server_zone_offset = get_time_zone(t);
- return server_zone_offset;
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ return ts;
}
-/*******************************************************************
- Re-read the smb serverzone value.
-******************************************************************/
-
-static struct timeval start_time_hires;
-
-void TimeInit(void)
-{
- set_server_zone_offset(time(NULL));
-
- DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
-
- /* Save the start time of this process. */
- if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
- GetTimeOfDay(&start_time_hires);
- }
-}
-
-/**********************************************************************
- Return a timeval struct of the uptime of this process. As TimeInit is
- done before a daemon fork then this is the start time from the parent
- daemon start. JRA.
-***********************************************************************/
-
-void get_process_uptime(struct timeval *ret_time)
-{
- struct timeval time_now_hires;
-
- GetTimeOfDay(&time_now_hires);
- ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
- if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
- ret_time->tv_sec -= 1;
- ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
- } else {
- ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
- }
-}
-
-#if 0
-/****************************************************************************
- Return the UTC offset in seconds west of UTC, adjusted for extra time offset.
-**************************************************************************/
-
-int TimeDiff(time_t t)
-{
- return get_time_zone(t);
-}
+#if (SIZEOF_LONG == 8)
+#define TIME_FIXUP_CONSTANT_INT 11644473600L
+#elif (SIZEOF_LONG_LONG == 8)
+#define TIME_FIXUP_CONSTANT_INT 11644473600LL
#endif
-#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
-
/****************************************************************************
Interpret an 8 byte "filetime" structure to a time_t
It's originally in "100ns units since jan 1st 1601"
- An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0.
-
- Returns GMT.
-****************************************************************************/
-
-time_t nt_time_to_unix(NTTIME *nt)
-{
- double d;
- time_t ret;
- /* The next two lines are a fix needed for the
- broken SCO compiler. JRA. */
- time_t l_time_min = TIME_T_MIN;
- time_t l_time_max = TIME_T_MAX;
-
- if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
- return(0);
- }
-
- d = ((double)nt->high)*4.0*(double)(1<<30);
- d += (nt->low&0xFFF00000);
- d *= 1.0e-7;
-
- /* now adjust by 369 years to make the secs since 1970 */
- d -= TIME_FIXUP_CONSTANT;
+ An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
- if (d <= l_time_min) {
- return (l_time_min);
- }
-
- if (d >= l_time_max) {
- return (l_time_max);
- }
-
- ret = (time_t)(d+0.5);
- return(ret);
-}
-
-/****************************************************************************
- Convert a NTTIME structure to a time_t.
- It's originally in "100ns units".
-
- This is an absolute version of the one above.
- By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
- if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
-****************************************************************************/
+ tv_sec = 0
+ tv_nsec = 0;
-time_t nt_time_to_unix_abs(const NTTIME *nt)
-{
- double d;
- time_t ret;
- /* The next two lines are a fix needed for the
- broken SCO compiler. JRA. */
- time_t l_time_min = TIME_T_MIN;
- time_t l_time_max = TIME_T_MAX;
- NTTIME neg_nt;
-
- if (nt->high == 0) {
- return(0);
- }
-
- if (nt->high==0x80000000 && nt->low==0) {
- return (time_t)-1;
- }
-
- /* reverse the time */
- /* it's a negative value, turn it to positive */
- neg_nt.high=~nt->high;
- neg_nt.low=~nt->low;
-
- d = ((double)neg_nt.high)*4.0*(double)(1<<30);
- d += (neg_nt.low&0xFFF00000);
- d *= 1.0e-7;
-
- if (!(l_time_min <= d && d <= l_time_max)) {
- return(0);
- }
-
- ret = (time_t)(d+0.5);
-
- return(ret);
-}
-
-/****************************************************************************
- Interprets an nt time into a unix time_t.
- Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
- will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
+ Returns GMT.
****************************************************************************/
-time_t interpret_long_date(char *p)
+time_t nt_time_to_unix(NTTIME nt)
{
- NTTIME nt;
- nt.low = IVAL(p,0);
- nt.high = IVAL(p,4);
- if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) {
- return (time_t)-1;
- }
- return nt_time_to_unix(&nt);
+ return convert_timespec_to_time_t(nt_time_to_unix_timespec(&nt));
}
/****************************************************************************
@@ -283,137 +93,81 @@ time_t interpret_long_date(char *p)
void unix_to_nt_time(NTTIME *nt, time_t t)
{
- double d;
+ uint64_t t2;
- if (t==0) {
- nt->low = 0;
- nt->high = 0;
- return;
- }
- if (t == TIME_T_MAX) {
- nt->low = 0xffffffff;
- nt->high = 0x7fffffff;
- return;
- }
if (t == (time_t)-1) {
- nt->low = 0xffffffff;
- nt->high = 0xffffffff;
+ *nt = (NTTIME)-1LL;
return;
}
-
- d = (double)(t);
- d += TIME_FIXUP_CONSTANT;
- d *= 1.0e7;
-
- nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
- nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
-}
-
-/****************************************************************************
- Convert a time_t to a NTTIME structure
-
- This is an absolute version of the one above.
- By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
- If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM
-****************************************************************************/
-
-void unix_to_nt_time_abs(NTTIME *nt, time_t t)
-{
- double d;
-
- if (t==0) {
- nt->low = 0;
- nt->high = 0;
- return;
- }
-
- if (t == TIME_T_MAX) {
- nt->low = 0xffffffff;
- nt->high = 0x7fffffff;
- return;
- }
-
- if (t == (time_t)-1) {
- /* that's what NT uses for infinite */
- nt->low = 0x0;
- nt->high = 0x80000000;
+ if (t == 0) {
+ *nt = 0;
return;
}
- d = (double)(t);
- d *= 1.0e7;
-
- nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
- nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
+ t2 = t;
+ t2 += TIME_FIXUP_CONSTANT_INT;
+ t2 *= 1000*1000*10;
- /* convert to a negative value */
- nt->high=~nt->high;
- nt->low=~nt->low;
+ *nt = t2;
}
-/****************************************************************************
- Take a Unix time and convert to an NTTIME structure and place in buffer
- pointed to by p.
-****************************************************************************/
-void put_long_date(char *p, time_t t)
+/**
+check if it's a null unix time
+**/
+BOOL null_time(time_t t)
{
- NTTIME nt;
- unix_to_nt_time(&nt, t);
- SIVAL(p, 0, nt.low);
- SIVAL(p, 4, nt.high);
+ return t == 0 ||
+ t == (time_t)0xFFFFFFFF ||
+ t == (time_t)-1;
}
-/****************************************************************************
- Check if it's a null mtime.
-****************************************************************************/
-BOOL null_mtime(time_t mtime)
+/**
+check if it's a null NTTIME
+**/
+BOOL null_nttime(NTTIME t)
{
- if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
- return(True);
- return(False);
+ return t == 0 || t == (NTTIME)-1;
}
/*******************************************************************
- Create a 16 bit dos packed date.
+ create a 16 bit dos packed date
********************************************************************/
-
-static uint16 make_dos_date1(struct tm *t)
+static uint16_t make_dos_date1(struct tm *t)
{
- uint16 ret=0;
- ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
+ uint16_t ret=0;
+ ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
- return(ret);
+ return ret;
}
/*******************************************************************
- Create a 16 bit dos packed time.
+ create a 16 bit dos packed time
********************************************************************/
-
-static uint16 make_dos_time1(struct tm *t)
+static uint16_t make_dos_time1(struct tm *t)
{
- uint16 ret=0;
- ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
+ uint16_t ret=0;
+ ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
- return(ret);
+ return ret;
}
/*******************************************************************
- Create a 32 bit dos packed date/time from some parameters.
- This takes a GMT time and returns a packed localtime structure.
+ create a 32 bit dos packed date/time from some parameters
+ This takes a GMT time and returns a packed localtime structure
********************************************************************/
-
-static uint32 make_dos_date(time_t unixdate, int zone_offset)
+static uint32_t make_dos_date(time_t unixdate, int zone_offset)
{
struct tm *t;
- uint32 ret=0;
+ uint32_t ret=0;
if (unixdate == 0) {
return 0;
}
unixdate -= zone_offset;
+
t = gmtime(&unixdate);
if (!t) {
return 0xFFFFFFFF;
@@ -422,53 +176,50 @@ static uint32 make_dos_date(time_t unixdate, int zone_offset)
ret = make_dos_date1(t);
ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
- return(ret);
+ return ret;
}
-/*******************************************************************
- Put a dos date into a buffer (time/date format).
- This takes GMT time and puts local time in the buffer.
-********************************************************************/
-
-static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
+/**
+put a dos date into a buffer (time/date format)
+This takes GMT time and puts local time in the buffer
+**/
+void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
{
- uint32 x = make_dos_date(unixdate, zone_offset);
+ uint32_t x = make_dos_date(unixdate, zone_offset);
SIVAL(buf,offset,x);
}
-/*******************************************************************
- Put a dos date into a buffer (date/time format).
- This takes GMT time and puts local time in the buffer.
-********************************************************************/
-
-static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
+/**
+put a dos date into a buffer (date/time format)
+This takes GMT time and puts local time in the buffer
+**/
+void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
{
- uint32 x = make_dos_date(unixdate, zone_offset);
+ uint32_t x;
+ x = make_dos_date(unixdate, zone_offset);
x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
SIVAL(buf,offset,x);
}
-/*******************************************************************
- Put a dos 32 bit "unix like" date into a buffer. This routine takes
- GMT and converts it to LOCAL time before putting it (most SMBs assume
- localtime for this sort of date)
-********************************************************************/
-
-static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
+/**
+put a dos 32 bit "unix like" date into a buffer. This routine takes
+GMT and converts it to LOCAL time before putting it (most SMBs assume
+localtime for this sort of date)
+**/
+void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
{
- if (!null_mtime(unixdate)) {
+ if (!null_time(unixdate)) {
unixdate -= zone_offset;
}
SIVAL(buf,offset,unixdate);
}
/*******************************************************************
- Interpret a 32 bit dos packed date/time to some parameters.
+ interpret a 32 bit dos packed date/time to some parameters
********************************************************************/
-
-static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
+static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
{
- uint32 p0,p1,p2,p3;
+ uint32_t p0,p1,p2,p3;
p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
@@ -481,161 +232,414 @@ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *ho
*year = ((p3>>1)&0xFF) + 80;
}
-/*******************************************************************
- Create a unix date (int GMT) from a dos date (which is actually in
- localtime).
-********************************************************************/
-
-static time_t make_unix_date(void *date_ptr, int zone_offset)
+/**
+ create a unix date (int GMT) from a dos date (which is actually in
+ localtime)
+**/
+time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
{
- uint32 dos_date=0;
+ uint32_t dos_date=0;
struct tm t;
time_t ret;
dos_date = IVAL(date_ptr,0);
- if (dos_date == 0) {
- return 0;
- }
+ if (dos_date == 0) return (time_t)0;
interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
- &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
+ &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
t.tm_isdst = -1;
ret = timegm(&t);
ret += zone_offset;
- return(ret);
+ return ret;
}
-/*******************************************************************
- Like make_unix_date() but the words are reversed.
-********************************************************************/
-
-static time_t make_unix_date2(void *date_ptr, int zone_offset)
+/**
+like make_unix_date() but the words are reversed
+**/
+time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
{
- uint32 x,x2;
+ uint32_t x,x2;
x = IVAL(date_ptr,0);
x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
SIVAL(&x,0,x2);
- return(make_unix_date((void *)&x, zone_offset));
+ return pull_dos_date((const uint8_t *)&x, zone_offset);
}
-/*******************************************************************
- Create a unix GMT date from a dos date in 32 bit "unix like" format
- these generally arrive as localtimes, with corresponding DST.
-******************************************************************/
-
-static time_t make_unix_date3(void *date_ptr, int zone_offset)
+/**
+ create a unix GMT date from a dos date in 32 bit "unix like" format
+ these generally arrive as localtimes, with corresponding DST
+**/
+time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
{
time_t t = (time_t)IVAL(date_ptr,0);
- if (!null_mtime(t)) {
+ if (!null_time(t)) {
t += zone_offset;
}
- return(t);
+ return t;
}
/***************************************************************************
- Server versions of the above functions.
+ Return a HTTP/1.0 time string.
***************************************************************************/
-void srv_put_dos_date(char *buf,int offset,time_t unixdate)
+char *http_timestring(time_t t)
{
- put_dos_date(buf, offset, unixdate, server_zone_offset);
+ static fstring buf;
+ struct tm *tm = localtime(&t);
+
+ if (!tm) {
+ slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
+ } else {
+#ifndef HAVE_STRFTIME
+ const char *asct = asctime(tm);
+ fstrcpy(buf, asct ? asct : "unknown");
+ }
+ if(buf[strlen(buf)-1] == '\n') {
+ buf[strlen(buf)-1] = 0;
+#else /* !HAVE_STRFTIME */
+ strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
+#endif /* !HAVE_STRFTIME */
+ }
+ return buf;
}
-void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
+
+/**
+ Return the date and time as a string
+**/
+char *timestring(TALLOC_CTX *mem_ctx, time_t t)
{
- put_dos_date2(buf, offset, unixdate, server_zone_offset);
+ char *TimeBuf;
+ char tempTime[80];
+ struct tm *tm;
+
+ tm = localtime(&t);
+ if (!tm) {
+ return talloc_asprintf(mem_ctx,
+ "%ld seconds since the Epoch",
+ (long)t);
+ }
+
+#ifdef HAVE_STRFTIME
+ /* some versions of gcc complain about using %c. This is a bug
+ in the gcc warning, not a bug in this code. See a recent
+ strftime() manual page for details.
+ */
+ strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm);
+ TimeBuf = talloc_strdup(mem_ctx, tempTime);
+#else
+ TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
+#endif
+
+ return TimeBuf;
}
-void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
+/**
+ return a talloced string representing a NTTIME for human consumption
+*/
+const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
{
- put_dos_date3(buf, offset, unixdate, server_zone_offset);
+ time_t t;
+ if (nt == 0) {
+ return "NTTIME(0)";
+ }
+ t = nt_time_to_unix(nt);
+ return timestring(mem_ctx, t);
}
-time_t srv_make_unix_date(void *date_ptr)
+
+/**
+ parse a nttime as a large integer in a string and return a NTTIME
+*/
+NTTIME nttime_from_string(const char *s)
{
- return make_unix_date(date_ptr, server_zone_offset);
+ return strtoull(s, NULL, 0);
}
-time_t srv_make_unix_date2(void *date_ptr)
+/**
+ return (tv1 - tv2) in microseconds
+*/
+int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2)
{
- return make_unix_date2(date_ptr, server_zone_offset);
+ int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
+ return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
}
-time_t srv_make_unix_date3(void *date_ptr)
+
+/**
+ return a zero timeval
+*/
+struct timeval timeval_zero(void)
{
- return make_unix_date3(date_ptr, server_zone_offset);
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ return tv;
}
-/***************************************************************************
- Client versions of the above functions.
-***************************************************************************/
+/**
+ return True if a timeval is zero
+*/
+BOOL timeval_is_zero(const struct timeval *tv)
+{
+ return tv->tv_sec == 0 && tv->tv_usec == 0;
+}
-void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
+/**
+ return a timeval for the current time
+*/
+struct timeval timeval_current(void)
{
- put_dos_date(buf, offset, unixdate, cli->serverzone);
+ struct timeval tv;
+ GetTimeOfDay(&tv);
+ return tv;
}
-void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
+/**
+ return a timeval struct with the given elements
+*/
+struct timeval timeval_set(uint32_t secs, uint32_t usecs)
{
- put_dos_date2(buf, offset, unixdate, cli->serverzone);
+ struct timeval tv;
+ tv.tv_sec = secs;
+ tv.tv_usec = usecs;
+ return tv;
}
-void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
+
+/**
+ return a timeval ofs microseconds after tv
+*/
+struct timeval timeval_add(const struct timeval *tv,
+ uint32_t secs, uint32_t usecs)
{
- put_dos_date3(buf, offset, unixdate, cli->serverzone);
+ struct timeval tv2 = *tv;
+ const unsigned int million = 1000000;
+ tv2.tv_sec += secs;
+ tv2.tv_usec += usecs;
+ tv2.tv_sec += tv2.tv_usec / million;
+ tv2.tv_usec = tv2.tv_usec % million;
+ return tv2;
}
-time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr)
+/**
+ return the sum of two timeval structures
+*/
+struct timeval timeval_sum(const struct timeval *tv1,
+ const struct timeval *tv2)
{
- return make_unix_date(date_ptr, cli->serverzone);
+ return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
}
-time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr)
+/**
+ return a timeval secs/usecs into the future
+*/
+struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
{
- return make_unix_date2(date_ptr, cli->serverzone);
+ struct timeval tv = timeval_current();
+ return timeval_add(&tv, secs, usecs);
}
-time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr)
+/**
+ compare two timeval structures.
+ Return -1 if tv1 < tv2
+ Return 0 if tv1 == tv2
+ Return 1 if tv1 > tv2
+*/
+int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
{
- return make_unix_date3(date_ptr, cli->serverzone);
+ if (tv1->tv_sec > tv2->tv_sec) return 1;
+ if (tv1->tv_sec < tv2->tv_sec) return -1;
+ if (tv1->tv_usec > tv2->tv_usec) return 1;
+ if (tv1->tv_usec < tv2->tv_usec) return -1;
+ return 0;
}
-/***************************************************************************
- Return a HTTP/1.0 time string.
-***************************************************************************/
+/**
+ return True if a timer is in the past
+*/
+BOOL timeval_expired(const struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ if (tv2.tv_sec > tv->tv_sec) return True;
+ if (tv2.tv_sec < tv->tv_sec) return False;
+ return (tv2.tv_usec >= tv->tv_usec);
+}
-char *http_timestring(time_t t)
+/**
+ return the number of seconds elapsed between two times
+*/
+double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
{
- static fstring buf;
- struct tm *tm = localtime(&t);
+ return (tv2->tv_sec - tv1->tv_sec) +
+ (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
+}
- if (!tm) {
- slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
+/**
+ return the number of seconds elapsed since a given time
+*/
+double timeval_elapsed(const struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ return timeval_elapsed2(tv, &tv2);
+}
+
+/**
+ return the lesser of two timevals
+*/
+struct timeval timeval_min(const struct timeval *tv1,
+ const struct timeval *tv2)
+{
+ if (tv1->tv_sec < tv2->tv_sec) return *tv1;
+ if (tv1->tv_sec > tv2->tv_sec) return *tv2;
+ if (tv1->tv_usec < tv2->tv_usec) return *tv1;
+ return *tv2;
+}
+
+/**
+ return the greater of two timevals
+*/
+struct timeval timeval_max(const struct timeval *tv1,
+ const struct timeval *tv2)
+{
+ if (tv1->tv_sec > tv2->tv_sec) return *tv1;
+ if (tv1->tv_sec < tv2->tv_sec) return *tv2;
+ if (tv1->tv_usec > tv2->tv_usec) return *tv1;
+ return *tv2;
+}
+
+/**
+ return the difference between two timevals as a timeval
+ if tv1 comes after tv2, then return a zero timeval
+ (this is *tv2 - *tv1)
+*/
+struct timeval timeval_until(const struct timeval *tv1,
+ const struct timeval *tv2)
+{
+ struct timeval t;
+ if (timeval_compare(tv1, tv2) >= 0) {
+ return timeval_zero();
+ }
+ t.tv_sec = tv2->tv_sec - tv1->tv_sec;
+ if (tv1->tv_usec > tv2->tv_usec) {
+ t.tv_sec--;
+ t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
} else {
-#ifndef HAVE_STRFTIME
- const char *asct = asctime(tm);
- fstrcpy(buf, asct ? asct : "unknown");
+ t.tv_usec = tv2->tv_usec - tv1->tv_usec;
}
- if(buf[strlen(buf)-1] == '\n') {
- buf[strlen(buf)-1] = 0;
-#else /* !HAVE_STRFTIME */
- strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
-#endif /* !HAVE_STRFTIME */
+ return t;
+}
+
+
+/**
+ convert a timeval to a NTTIME
+*/
+NTTIME timeval_to_nttime(const struct timeval *tv)
+{
+ return 10*(tv->tv_usec +
+ ((TIME_FIXUP_CONSTANT_INT + (uint64_t)tv->tv_sec) * 1000000));
+}
+
+/*******************************************************************
+yield the difference between *A and *B, in seconds, ignoring leap seconds
+********************************************************************/
+static int tm_diff(struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (1900 - 1);
+ int by = b->tm_year + (1900 - 1);
+ int intervening_leap_days =
+ (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
+ int years = ay - by;
+ int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
+ int hours = 24*days + (a->tm_hour - b->tm_hour);
+ int minutes = 60*hours + (a->tm_min - b->tm_min);
+ int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
+
+ return seconds;
+}
+
+int extra_time_offset=0;
+
+/**
+ return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
+ */
+int get_time_zone(time_t t)
+{
+ struct tm *tm = gmtime(&t);
+ struct tm tm_utc;
+ if (!tm)
+ return 0;
+ tm_utc = *tm;
+ tm = localtime(&t);
+ if (!tm)
+ return 0;
+ return tm_diff(&tm_utc,tm)+60*extra_time_offset;
+}
+
+/****************************************************************************
+ Check if NTTIME is 0.
+****************************************************************************/
+
+BOOL nt_time_is_zero(const NTTIME *nt)
+{
+ return (*nt == 0);
+}
+
+/****************************************************************************
+ 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;
}
- return buf;
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+
+ return timegm(&tm);
+}
+
+/*******************************************************************
+ Accessor function for the server time zone offset.
+ set_server_zone_offset() must have been called first.
+******************************************************************/
+
+static int server_zone_offset;
+
+int get_server_zone_offset(void)
+{
+ return server_zone_offset;
+}
+
+/*******************************************************************
+ Initialize the server time zone offset. Called when a client connects.
+******************************************************************/
+
+int set_server_zone_offset(time_t t)
+{
+ server_zone_offset = get_time_zone(t);
+ return server_zone_offset;
}
/****************************************************************************
Return the date and time as a string
****************************************************************************/
-char *timestring(BOOL hires)
+char *current_timestring(BOOL hires)
{
static fstring TimeBuf;
struct timeval tp;
@@ -690,6 +694,85 @@ char *timestring(BOOL hires)
return(TimeBuf);
}
+
+/*******************************************************************
+ Put a dos date into a buffer (time/date format).
+ This takes GMT time and puts local time in the buffer.
+********************************************************************/
+
+static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
+{
+ uint32 x = make_dos_date(unixdate, zone_offset);
+ SIVAL(buf,offset,x);
+}
+
+/*******************************************************************
+ Put a dos date into a buffer (date/time format).
+ This takes GMT time and puts local time in the buffer.
+********************************************************************/
+
+static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
+{
+ uint32 x = make_dos_date(unixdate, zone_offset);
+ x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
+ SIVAL(buf,offset,x);
+}
+
+/*******************************************************************
+ Put a dos 32 bit "unix like" date into a buffer. This routine takes
+ GMT and converts it to LOCAL time before putting it (most SMBs assume
+ localtime for this sort of date)
+********************************************************************/
+
+static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
+{
+ if (!null_mtime(unixdate)) {
+ unixdate -= zone_offset;
+ }
+ SIVAL(buf,offset,unixdate);
+}
+
+
+/***************************************************************************
+ Server versions of the above functions.
+***************************************************************************/
+
+void srv_put_dos_date(char *buf,int offset,time_t unixdate)
+{
+ put_dos_date(buf, offset, unixdate, server_zone_offset);
+}
+
+void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
+{
+ put_dos_date2(buf, offset, unixdate, server_zone_offset);
+}
+
+void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
+{
+ put_dos_date3(buf, offset, unixdate, server_zone_offset);
+}
+
+/****************************************************************************
+ Take a Unix time and convert to an NTTIME structure and place in buffer
+ pointed to by p.
+****************************************************************************/
+
+void put_long_date_timespec(char *p, struct timespec ts)
+{
+ NTTIME nt;
+ unix_timespec_to_nt_time(&nt, ts);
+ SIVAL(p, 0, nt & 0xFFFFFFFF);
+ SIVAL(p, 4, nt >> 32);
+}
+
+void put_long_date(char *p, time_t t)
+{
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ put_long_date_timespec(p, ts);
+}
+
/****************************************************************************
Return the best approximation to a 'create time' under UNIX from a stat
structure.
@@ -717,344 +800,478 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
return ret;
}
+struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+{
+ struct timespec ts;
+ ts.tv_sec = get_create_time(st, fake_dirs);
+ ts.tv_nsec = 0;
+ return ts;
+}
+
/****************************************************************************
- Initialise an NTTIME to -1, which means "unknown" or "don't expire".
+ Get/Set all the possible time fields from a stat struct as a timespec.
****************************************************************************/
-void init_nt_time(NTTIME *nt)
+struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
{
- nt->high = 0x7FFFFFFF;
- nt->low = 0xFFFFFFFF;
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->st_atime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_ATIM)
+ return pst->st_atim;
+#elif defined(HAVE_STAT_ST_ATIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_atime;
+ ret.tv_nsec = pst->st_atimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
}
-BOOL nt_time_is_set(const NTTIME *nt)
+void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
{
- if ((nt->high == 0x7FFFFFFF) && (nt->low == 0xFFFFFFFF)) {
- return False;
- }
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_atime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_ATIM)
+ pst->st_atim = ts;
+#elif defined(HAVE_STAT_ST_ATIMENSEC)
+ pst->st_atime = ts.tv_sec;
+ pst->st_atimensec = ts.tv_nsec
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
- if ((nt->high == 0x80000000) && (nt->low == 0)) {
- return False;
- }
+struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
- return True;
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->st_mtime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_MTIM)
+ return pst->st_mtim;
+#elif defined(HAVE_STAT_ST_MTIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_mtime;
+ ret.tv_nsec = pst->st_mtimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
}
-/****************************************************************************
- Check if NTTIME is 0.
-****************************************************************************/
+void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_mtime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_MTIM)
+ pst->st_mtim = ts;
+#elif defined(HAVE_STAT_ST_MTIMENSEC)
+ pst->st_mtime = ts.tv_sec;
+ pst->st_mtimensec = ts.tv_nsec
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
-BOOL nt_time_is_zero(const NTTIME *nt)
+struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
{
- if(nt->high==0) {
- return True;
- }
- return False;
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->st_ctime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_CTIM)
+ return pst->st_ctim;
+#elif defined(HAVE_STAT_ST_CTIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_ctime;
+ ret.tv_nsec = pst->st_ctimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
}
-/****************************************************************************
- Check if two NTTIMEs are the same.
-****************************************************************************/
+void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_ctime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_CTIM)
+ pst->st_ctim = ts;
+#elif defined(HAVE_STAT_ST_CTIMENSEC)
+ pst->st_ctime = ts.tv_sec;
+ pst->st_ctimensec = ts.tv_nsec
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
-BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
+void dos_filetime_timespec(struct timespec *tsp)
{
- return (nt1->high == nt2->high && nt1->low == nt2->low);
+ tsp->tv_sec &= ~1;
+ tsp->tv_nsec = 0;
}
-/****************************************************************************
- Return a timeval difference in usec.
-****************************************************************************/
+/*******************************************************************
+ Create a unix date (int GMT) from a dos date (which is actually in
+ localtime).
+********************************************************************/
-SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *smallt)
+static time_t make_unix_date(const void *date_ptr, int zone_offset)
{
- SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec;
- return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec);
+ uint32 dos_date=0;
+ struct tm t;
+ time_t ret;
+
+ dos_date = IVAL(date_ptr,0);
+
+ if (dos_date == 0) {
+ return 0;
+ }
+
+ interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
+ &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
+ t.tm_isdst = -1;
+
+ ret = timegm(&t);
+
+ ret += zone_offset;
+
+ return(ret);
}
-/****************************************************************************
- Return a timeval struct with the given elements.
-****************************************************************************/
+/*******************************************************************
+ Like make_unix_date() but the words are reversed.
+********************************************************************/
-struct timeval timeval_set(uint32_t secs, uint32_t usecs)
+static time_t make_unix_date2(const void *date_ptr, int zone_offset)
{
- struct timeval tv;
- tv.tv_sec = secs;
- tv.tv_usec = usecs;
- return tv;
+ uint32 x,x2;
+
+ x = IVAL(date_ptr,0);
+ x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
+ SIVAL(&x,0,x2);
+
+ return(make_unix_date((const void *)&x, zone_offset));
}
-/****************************************************************************
- Return a zero timeval.
-****************************************************************************/
+/*******************************************************************
+ Create a unix GMT date from a dos date in 32 bit "unix like" format
+ these generally arrive as localtimes, with corresponding DST.
+******************************************************************/
-struct timeval timeval_zero(void)
+static time_t make_unix_date3(const void *date_ptr, int zone_offset)
{
- return timeval_set(0,0);
+ time_t t = (time_t)IVAL(date_ptr,0);
+ if (!null_mtime(t)) {
+ t += zone_offset;
+ }
+ return(t);
}
-/****************************************************************************
- Return True if a timeval is zero.
-****************************************************************************/
+time_t srv_make_unix_date(const void *date_ptr)
+{
+ return make_unix_date(date_ptr, server_zone_offset);
+}
-BOOL timeval_is_zero(const struct timeval *tv)
+time_t srv_make_unix_date2(const void *date_ptr)
{
- return tv->tv_sec == 0 && tv->tv_usec == 0;
+ return make_unix_date2(date_ptr, server_zone_offset);
}
-/****************************************************************************
- Return a timeval for the current time.
-****************************************************************************/
+time_t srv_make_unix_date3(const void *date_ptr)
+{
+ return make_unix_date3(date_ptr, server_zone_offset);
+}
-struct timeval timeval_current(void)
+time_t convert_timespec_to_time_t(struct timespec ts)
{
- struct timeval tv;
- GetTimeOfDay(&tv);
- return tv;
+ /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
+ increment if it's greater than 500 millionth of a second. */
+ if (ts.tv_nsec > 500000000) {
+ return ts.tv_sec + 1;
+ }
+ return ts.tv_sec;
}
/****************************************************************************
- Return a timeval ofs microseconds after tv.
+ Interprets an nt time into a unix struct timespec.
+ Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
+ will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
****************************************************************************/
-struct timeval timeval_add(const struct timeval *tv,
- uint32_t secs, uint32_t usecs)
+struct timespec interpret_long_date(const char *p)
{
- struct timeval tv2 = *tv;
- tv2.tv_sec += secs;
- tv2.tv_usec += usecs;
- tv2.tv_sec += tv2.tv_usec / 1000000;
- tv2.tv_usec = tv2.tv_usec % 1000000;
- return tv2;
+ NTTIME nt;
+ nt = IVAL(p,0) + ((uint64_t)IVAL(p,4) << 32);
+ if (nt == (uint64_t)-1) {
+ struct timespec ret;
+ ret.tv_sec = (time_t)-1;
+ ret.tv_nsec = 0;
+ return ret;
+ }
+ return nt_time_to_unix_timespec(&nt);
}
-/****************************************************************************
- Return the sum of two timeval structures.
-****************************************************************************/
+/***************************************************************************
+ Client versions of the above functions.
+***************************************************************************/
-struct timeval timeval_sum(const struct timeval *tv1,
- const struct timeval *tv2)
+void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
{
- return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
+ put_dos_date(buf, offset, unixdate, cli->serverzone);
}
-/****************************************************************************
- Return a timeval secs/usecs into the future.
-****************************************************************************/
+void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
+{
+ put_dos_date2(buf, offset, unixdate, cli->serverzone);
+}
-struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
+void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
{
- struct timeval tv = timeval_current();
- return timeval_add(&tv, secs, usecs);
+ put_dos_date3(buf, offset, unixdate, cli->serverzone);
}
-/****************************************************************************
- Compare two timeval structures.
- Return -1 if tv1 < tv2
- Return 0 if tv1 == tv2
- Return 1 if tv1 > tv2
-****************************************************************************/
+time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr)
+{
+ return make_unix_date(date_ptr, cli->serverzone);
+}
-int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
+time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr)
{
- if (tv1->tv_sec > tv2->tv_sec) {
- return 1;
- }
- if (tv1->tv_sec < tv2->tv_sec) {
- return -1;
+ return make_unix_date2(date_ptr, cli->serverzone);
+}
+
+time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr)
+{
+ return make_unix_date3(date_ptr, cli->serverzone);
+}
+
+/* Large integer version. */
+struct timespec nt_time_to_unix_timespec(NTTIME *nt)
+{
+ int64 d;
+ struct timespec ret;
+
+ if (*nt == 0 || *nt == (int64)-1) {
+ ret.tv_sec = 0;
+ ret.tv_nsec = 0;
+ return ret;
}
- if (tv1->tv_usec > tv2->tv_usec) {
- return 1;
+
+ d = (int64)*nt;
+ /* d is now in 100ns units, since jan 1st 1601".
+ Save off the ns fraction. */
+
+ ret.tv_nsec = (long) ((d % 100) * 100);
+
+ /* Convert to seconds */
+ d /= 1000*1000*10;
+
+ /* Now adjust by 369 years to make the secs since 1970 */
+ d -= TIME_FIXUP_CONSTANT_INT;
+
+ if (d <= (int64)TIME_T_MIN) {
+ ret.tv_sec = TIME_T_MIN;
+ ret.tv_nsec = 0;
+ return ret;
}
- if (tv1->tv_usec < tv2->tv_usec) {
- return -1;
+
+ if (d >= (int64)TIME_T_MAX) {
+ ret.tv_sec = TIME_T_MAX;
+ ret.tv_nsec = 0;
+ return ret;
}
- return 0;
-}
+ ret.tv_sec = (time_t)d;
+ return ret;
+}
/****************************************************************************
- Return the difference between two timevals as a timeval.
- If tv1 comes after tv2, then return a zero timeval
- (this is *tv2 - *tv1).
+ Check if two NTTIMEs are the same.
****************************************************************************/
-struct timeval timeval_until(const struct timeval *tv1,
- const struct timeval *tv2)
+BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
{
- struct timeval t;
- if (timeval_compare(tv1, tv2) >= 0) {
- return timeval_zero();
- }
- t.tv_sec = tv2->tv_sec - tv1->tv_sec;
- if (tv1->tv_usec > tv2->tv_usec) {
- t.tv_sec--;
- t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
- } else {
- t.tv_usec = tv2->tv_usec - tv1->tv_usec;
- }
- return t;
+ return (*nt1 == *nt2);
}
-/****************************************************************************
- Return the lesser of two timevals.
-****************************************************************************/
+/*******************************************************************
+ Re-read the smb serverzone value.
+******************************************************************/
-struct timeval timeval_min(const struct timeval *tv1,
- const struct timeval *tv2)
+static struct timeval start_time_hires;
+
+void TimeInit(void)
{
- if (tv1->tv_sec < tv2->tv_sec) {
- return *tv1;
- }
- if (tv1->tv_sec > tv2->tv_sec) {
- return *tv2;
+ set_server_zone_offset(time(NULL));
+
+ DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
+
+ /* Save the start time of this process. */
+ if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
+ GetTimeOfDay(&start_time_hires);
}
- if (tv1->tv_usec < tv2->tv_usec) {
- return *tv1;
+}
+
+/**********************************************************************
+ Return a timeval struct of the uptime of this process. As TimeInit is
+ done before a daemon fork then this is the start time from the parent
+ daemon start. JRA.
+***********************************************************************/
+
+void get_process_uptime(struct timeval *ret_time)
+{
+ struct timeval time_now_hires;
+
+ GetTimeOfDay(&time_now_hires);
+ ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
+ if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
+ ret_time->tv_sec -= 1;
+ ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
+ } else {
+ ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
}
- return *tv2;
}
/****************************************************************************
- Return the greater of two timevals.
+ Convert a NTTIME structure to a time_t.
+ It's originally in "100ns units".
+
+ This is an absolute version of the one above.
+ By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
+ if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
****************************************************************************/
-struct timeval timeval_max(const struct timeval *tv1,
- const struct timeval *tv2)
+time_t nt_time_to_unix_abs(const NTTIME *nt)
{
- if (tv1->tv_sec > tv2->tv_sec) {
- return *tv1;
+ uint64 d;
+
+ if (*nt == 0) {
+ return (time_t)0;
}
- if (tv1->tv_sec < tv2->tv_sec) {
- return *tv2;
+
+ if (*nt == (uint64)-1) {
+ return (time_t)-1;
}
- if (tv1->tv_usec > tv2->tv_usec) {
- return *tv1;
+
+ /* reverse the time */
+ /* it's a negative value, turn it to positive */
+ d=~*nt;
+
+ d += 1000*1000*10/2;
+ d /= 1000*1000*10;
+
+ if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
+ return (time_t)0;
}
- return *tv2;
+
+ return (time_t)d;
}
/****************************************************************************
- Convert ASN.1 GeneralizedTime string to unix-time.
- Returns 0 on failure; Currently ignores timezone.
+ Put a 8 byte filetime from a struct timespec. Uses GMT.
****************************************************************************/
-time_t generalized_to_unix_time(const char *str)
-{
- struct tm tm;
-
- ZERO_STRUCT(tm);
+void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
+{
+ uint64 d;
- 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;
+ if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
+ *nt = 0;
+ return;
}
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
+ if (ts.tv_sec == TIME_T_MAX) {
+ *nt = 0x7fffffffffffffffLL;
+ return;
+ }
+ if (ts.tv_sec == (time_t)-1) {
+ *nt = (uint64)-1;
+ return;
+ }
- return timegm(&tm);
+ d = ts.tv_sec;
+ d += TIME_FIXUP_CONSTANT_INT;
+ d *= 1000*1000*10;
+ /* d is now in 100ns units. */
+ d += (ts.tv_nsec / 100);
+
+ *nt = d;
}
/****************************************************************************
- Return all the possible time fields from a stat struct as a timespec.
+ Convert a time_t to a NTTIME structure
+
+ This is an absolute version of the one above.
+ By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
+ If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM
****************************************************************************/
-struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
+void unix_to_nt_time_abs(NTTIME *nt, time_t t)
{
-#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
- struct timespec ret;
+ double d;
- /* Old system - no ns timestamp. */
- ret.tv_sec = pst->st_atime;
- ret.tv_nsec = 0;
- return ret;
-#else
-#if defined(HAVE_STAT_ST_ATIM)
- return pst->st_atim;
-#elif defined(HAVE_STAT_ST_ATIMENSEC)
- struct timespec ret;
- ret.tv_sec = pst->st_atime;
- ret.tv_nsec = pst->st_atimensec;
- return ret;
-#else
-#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
-#endif
-#endif
-}
+ if (t==0) {
+ *nt = 0;
+ return;
+ }
-struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
-{
-#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
- struct timespec ret;
+ if (t == TIME_T_MAX) {
+ *nt = 0x7fffffffffffffffLL;
+ return;
+ }
+
+ if (t == (time_t)-1) {
+ /* that's what NT uses for infinite */
+ *nt = 0x8000000000000000LL;
+ return;
+ }
- /* Old system - no ns timestamp. */
- ret.tv_sec = pst->st_mtime;
- ret.tv_nsec = 0;
- return ret;
-#else
-#if defined(HAVE_STAT_ST_MTIM)
- return pst->st_mtim;
-#elif defined(HAVE_STAT_ST_MTIMENSEC)
- struct timespec ret;
- ret.tv_sec = pst->st_mtime;
- ret.tv_nsec = pst->st_mtimensec;
- return ret;
-#else
-#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
-#endif
-#endif
-}
+ d = (double)(t);
+ d *= 1.0e7;
-struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
-{
-#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
- struct timespec ret;
+ *nt = d;
- /* Old system - no ns timestamp. */
- ret.tv_sec = pst->st_ctime;
- ret.tv_nsec = 0;
- return ret;
-#else
-#if defined(HAVE_STAT_ST_CTIM)
- return pst->st_ctim;
-#elif defined(HAVE_STAT_ST_CTIMENSEC)
- struct timespec ret;
- ret.tv_sec = pst->st_ctime;
- ret.tv_nsec = pst->st_ctimensec;
- return ret;
-#else
-#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
-#endif
-#endif
+ /* convert to a negative value */
+ *nt=~*nt;
}
-#if 0
+
/****************************************************************************
- Return the best approximation to a 'create time' under UNIX from a stat
- structure.
+ Check if it's a null mtime.
****************************************************************************/
-struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+BOOL null_mtime(time_t mtime)
{
- time_t ret, ret1;
-
- if(S_ISDIR(st->st_mode) && fake_dirs) {
- return (time_t)315493200L; /* 1/1/1980 */
- }
-
- ret = MIN(st->st_ctime, st->st_mtime);
- ret1 = MIN(ret, st->st_atime);
-
- if(ret1 != (time_t)0) {
- return ret1;
- }
-
- /*
- * One of ctime, mtime or atime was zero (probably atime).
- * Just return MIN(ctime, mtime).
- */
- return ret;
+ if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
+ return(True);
+ return(False);
}
-#endif
/****************************************************************************
Utility function that always returns a const string even if localtime
@@ -1076,3 +1293,52 @@ const char *time_to_asc(const time_t *t)
}
return asct;
}
+
+const char *display_time(NTTIME nttime)
+{
+ static fstring string;
+
+ float high;
+ float low;
+ int sec;
+ int days, hours, mins, secs;
+
+ if (nttime==0)
+ return "Now";
+
+ if (nttime==0x8000000000000000LL)
+ return "Never";
+
+ high = 65536;
+ high = high/10000;
+ high = high*65536;
+ high = high/1000;
+ high = high * (~(nttime >> 32));
+
+ low = ~(nttime & 0xFFFFFFFF);
+ low = low/(1000*1000*10);
+
+ sec=high+low;
+
+ days=sec/(60*60*24);
+ hours=(sec - (days*60*60*24)) / (60*60);
+ mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
+ secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
+
+ fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
+ return (string);
+}
+
+BOOL nt_time_is_set(const NTTIME *nt)
+{
+ if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
+ return False;
+ }
+
+ if (*nt == 0x8000000000000000LL) {
+ return False;
+ }
+
+ return True;
+}
+
diff --git a/source/lib/util.c b/source/lib/util.c
index 9738326ce67..67c9c8d37a7 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -61,7 +61,7 @@ extern fstring remote_arch;
enum protocol_types Protocol = PROTOCOL_COREPLUS;
/* a default finfo structure to ensure all fields are sensible */
-file_info def_finfo = {-1,0,0,0,0,0,0,"",""};
+file_info def_finfo;
/* this is used by the chaining code */
int chain_size = 0;
@@ -199,10 +199,10 @@ void gfree_all( void )
gfree_case_tables();
gfree_debugsyms();
gfree_charcnv();
- gfree_messsges();
+ gfree_messages();
/* release the talloc null_context memory last */
- talloc_nc_free();
+ talloc_disable_null_tracking();
}
const char *my_netbios_names(int i)
@@ -307,7 +307,7 @@ const char *tmpdir(void)
Add a gid to an array of gids if it's not already there.
****************************************************************************/
-void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
+BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
gid_t **gids, size_t *num_gids)
{
int i;
@@ -316,26 +316,24 @@ void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
/*
* A former call to this routine has failed to allocate memory
*/
- return;
+ return False;
}
for (i=0; i<*num_gids; i++) {
- if ((*gids)[i] == gid)
- return;
- }
-
- if (mem_ctx != NULL) {
- *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
- } else {
- *gids = SMB_REALLOC_ARRAY(*gids, gid_t, *num_gids+1);
+ if ((*gids)[i] == gid) {
+ return True;
+ }
}
+ *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
if (*gids == NULL) {
- return;
+ *num_gids = 0;
+ return False;
}
(*gids)[*num_gids] = gid;
*num_gids += 1;
+ return True;
}
/****************************************************************************
@@ -760,7 +758,7 @@ ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)
size_t num_to_read_thistime;
size_t num_written = 0;
- if ((buf = SMB_MALLOC(TRANSFER_BUF_SIZE)) == NULL)
+ if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
return -1;
while (total < n) {
@@ -915,6 +913,17 @@ void *malloc_(size_t size)
}
/****************************************************************************
+ Internal malloc wrapper. Externally visible.
+****************************************************************************/
+
+void *memalign_(size_t align, size_t size)
+{
+#undef memalign
+ return memalign(align, size);
+#define memalign(align, s) __ERROR_DONT_USE_MEMALIGN_DIRECTLY
+}
+
+/****************************************************************************
Internal calloc wrapper. Not externally visible.
****************************************************************************/
@@ -956,6 +965,23 @@ void *malloc_array(size_t el_size, unsigned int count)
}
/****************************************************************************
+ Type-safe memalign
+****************************************************************************/
+
+void *memalign_array(size_t el_size, size_t align, unsigned int count)
+{
+ if (count >= MAX_ALLOC_SIZE/el_size) {
+ return NULL;
+ }
+
+#if defined(PARANOID_MALLOC_CHECKER)
+ return memalign_(align, el_size*count);
+#else
+ return sys_memalign(align, el_size*count);
+#endif
+}
+
+/****************************************************************************
Type-safe calloc.
****************************************************************************/
@@ -1059,9 +1085,11 @@ void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_o
****************************************************************************/
void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
- void *element, void **array, uint32 *num_elements,
+ void *element, void *_array, uint32 *num_elements,
ssize_t *array_size)
{
+ void **array = (void **)_array;
+
if (*array_size < 0) {
return;
}
@@ -1075,12 +1103,7 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
goto error;
}
- if (mem_ctx != NULL) {
- *array = TALLOC(mem_ctx, element_size * (*array_size));
- } else {
- *array = SMB_MALLOC(element_size * (*array_size));
- }
-
+ *array = TALLOC(mem_ctx, element_size * (*array_size));
if (*array == NULL) {
goto error;
}
@@ -1093,13 +1116,8 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
goto error;
}
- if (mem_ctx != NULL) {
- *array = TALLOC_REALLOC(mem_ctx, *array,
- element_size * (*array_size));
- } else {
- *array = SMB_REALLOC(*array,
- element_size * (*array_size));
- }
+ *array = TALLOC_REALLOC(mem_ctx, *array,
+ element_size * (*array_size));
if (*array == NULL) {
goto error;
@@ -1479,6 +1497,10 @@ BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
BOOL process_exists(const struct process_id pid)
{
+ if (procid_is_me(&pid)) {
+ return True;
+ }
+
if (!procid_is_local(&pid)) {
/* This *SEVERELY* needs fixing. */
return True;
@@ -1599,9 +1621,6 @@ void smb_panic(const char *const why)
(unsigned long long)sys_getpid(), why));
log_stack_trace();
- /* only smbd needs to decrement the smbd counter in connections.tdb */
- decrement_smbd_process_count();
-
cmd = lp_panic_action();
if (cmd && *cmd) {
DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
@@ -2138,6 +2157,7 @@ BOOL is_myworkgroup(const char *s)
/*******************************************************************
we distinguish between 2K and XP by the "Native Lan Manager" string
WinXP => "Windows 2002 5.1"
+ WinXP 64bit => "Windows XP 5.2"
Win2k => "Windows 2000 5.0"
NT4 => "Windows NT 4.0"
Win9x => "Windows 4.0"
@@ -2146,9 +2166,11 @@ BOOL is_myworkgroup(const char *s)
********************************************************************/
void ra_lanman_string( const char *native_lanman )
-{
+{
if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
set_remote_arch( RA_WINXP );
+ else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
+ set_remote_arch( RA_WINXP );
else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
set_remote_arch( RA_WIN2K3 );
}
@@ -2182,6 +2204,9 @@ void set_remote_arch(enum remote_arch_types type)
case RA_WIN2K3:
fstrcpy(remote_arch, "Win2K3");
break;
+ case RA_VISTA:
+ fstrcpy(remote_arch, "Vista");
+ break;
case RA_SAMBA:
fstrcpy(remote_arch,"Samba");
break;
@@ -2443,8 +2468,16 @@ char *smb_xstrdup(const char *s)
#undef strdup
#endif
#endif
+
+#ifndef HAVE_STRDUP
+#define strdup rep_strdup
+#endif
+
char *s1 = strdup(s);
#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef strdup
+#undef strdup
+#endif
#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
#endif
if (!s1)
@@ -2464,8 +2497,17 @@ char *smb_xstrndup(const char *s, size_t n)
#undef strndup
#endif
#endif
+
+#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
+#undef HAVE_STRNDUP
+#define strndup rep_strndup
+#endif
+
char *s1 = strndup(s, n);
#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef strndup
+#undef strndup
+#endif
#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
#endif
if (!s1)
@@ -2612,6 +2654,37 @@ char *parent_dirname(const char *path)
return dirpath;
}
+BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
+ char **parent, const char **name)
+{
+ char *p;
+ ptrdiff_t len;
+
+ p = strrchr_m(dir, '/'); /* Find final '/', if any */
+
+ if (p == NULL) {
+ if (!(*parent = talloc_strdup(mem_ctx, "."))) {
+ return False;
+ }
+ if (name) {
+ *name = "";
+ }
+ return True;
+ }
+
+ len = p-dir;
+
+ if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
+ return False;
+ }
+ memcpy(*parent, dir, len);
+ (*parent)[len] = '\0';
+
+ if (name) {
+ *name = p+1;
+ }
+ return True;
+}
/*******************************************************************
Determine if a pattern contains any Microsoft wildcard characters.
@@ -2829,10 +2902,11 @@ BOOL unix_wild_match(const char *pattern, const char *string)
}
/**********************************************************************
- Converts a name to a fully qalified domain name.
+ Converts a name to a fully qualified domain name.
+ Returns True if lookup succeeded, False if not (then fqdn is set to name)
***********************************************************************/
-void name_to_fqdn(fstring fqdn, const char *name)
+BOOL name_to_fqdn(fstring fqdn, const char *name)
{
struct hostent *hp = sys_gethostbyname(name);
@@ -2854,7 +2928,7 @@ void name_to_fqdn(fstring fqdn, const char *name)
if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
- DEBUGADD(1, (" to Kerberos authentication probelms as localhost.localdomain\n"));
+ DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
full = hp->h_name;
}
@@ -2865,9 +2939,11 @@ void name_to_fqdn(fstring fqdn, const char *name)
DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
fstrcpy(fqdn, full);
+ return True;
} else {
DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
fstrcpy(fqdn, name);
+ return False;
}
}
@@ -2968,11 +3044,24 @@ struct process_id procid_self(void)
return pid_to_procid(sys_getpid());
}
+struct server_id server_id_self(void)
+{
+ struct server_id id;
+ id.id = procid_self();
+ return id;
+}
+
BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
{
return (p1->pid == p2->pid);
}
+BOOL cluster_id_equal(const struct server_id *id1,
+ const struct server_id *id2)
+{
+ return procid_equal(&id1->id, &id2->id);
+}
+
BOOL procid_is_me(const struct process_id *pid)
{
return (pid->pid == sys_getpid());
diff --git a/source/lib/util_file.c b/source/lib/util_file.c
index ed7be3f6c1d..03246cad8e7 100644
--- a/source/lib/util_file.c
+++ b/source/lib/util_file.c
@@ -24,241 +24,6 @@
#define MAP_FAILED ((void *)-1)
#endif
-static int gotalarm;
-
-/***************************************************************
- Signal function to tell us we timed out.
-****************************************************************/
-
-static void gotalarm_sig(void)
-{
- gotalarm = 1;
-}
-
-/***************************************************************
- Lock or unlock a fd for a known lock type. Abandon after waitsecs
- seconds.
-****************************************************************/
-
-BOOL do_file_lock(int fd, int waitsecs, int type)
-{
- SMB_STRUCT_FLOCK lock;
- int ret;
- void (*oldsig_handler)(int);
-
- gotalarm = 0;
- oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
-
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- lock.l_pid = 0;
-
- alarm(waitsecs);
- /* Note we must *NOT* use sys_fcntl here ! JRA */
- ret = fcntl(fd, SMB_F_SETLKW, &lock);
- alarm(0);
- CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
-
- if (gotalarm) {
- DEBUG(0, ("do_file_lock: failed to %s file.\n",
- type == F_UNLCK ? "unlock" : "lock"));
- return False;
- }
-
- return (ret == 0);
-}
-
-/***************************************************************
- Lock an fd. Abandon after waitsecs seconds.
-****************************************************************/
-
-BOOL file_lock(int fd, int type, int secs, int *plock_depth)
-{
- if (fd < 0)
- return False;
-
- (*plock_depth)++;
-
- if ((*plock_depth) == 0) {
- if (!do_file_lock(fd, secs, type)) {
- DEBUG(10,("file_lock: locking file failed, error = %s.\n", strerror(errno)));
- return False;
- }
- }
-
- return True;
-}
-
-/***************************************************************
- Unlock an fd. Abandon after waitsecs seconds.
-****************************************************************/
-
-BOOL file_unlock(int fd, int *plock_depth)
-{
- BOOL ret=True;
-
- if(*plock_depth == 1) {
- ret = do_file_lock(fd, 5, F_UNLCK);
- }
-
- (*plock_depth)--;
-
- if(!ret) {
- DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", strerror(errno)));
- }
- return ret;
-}
-
-/***************************************************************
- Locks a file for enumeration / modification.
- update to be set = True if modification is required.
-****************************************************************/
-
-void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
- int *file_lock_depth, BOOL update)
-{
- FILE *fp = NULL;
-
- if (!*pfile) {
- DEBUG(0, ("startfilepwent: No file set\n"));
- return (NULL);
- }
- DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
-
- fp = sys_fopen(pfile, update ? "r+b" : "rb");
-
- if (fp == NULL) {
- DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
- return NULL;
- }
-
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, s_readbuf, _IOFBF, bufsize);
-
- if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) {
- DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
- fclose(fp);
- return NULL;
- }
-
- /* Make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* We have a lock on the file. */
- return (void *)fp;
-}
-
-/***************************************************************
- End enumeration of the file.
-****************************************************************/
-
-void endfilepwent(void *vp, int *file_lock_depth)
-{
- FILE *fp = (FILE *)vp;
-
- file_unlock(fileno(fp), file_lock_depth);
- fclose(fp);
- DEBUG(7, ("endfilepwent: closed file.\n"));
-}
-
-/*************************************************************************
- Return the current position in the file list as an SMB_BIG_UINT.
- This must be treated as an opaque token.
-*************************************************************************/
-
-SMB_BIG_UINT getfilepwpos(void *vp)
-{
- return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
-}
-
-/*************************************************************************
- Set the current position in the file list from an SMB_BIG_UINT.
- This must be treated as an opaque token.
-*************************************************************************/
-
-BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
-{
- return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
-}
-
-/*************************************************************************
- Gets a line out of a file.
- line is of format "xxxx:xxxxxx:xxxxx:".
- lines with "#" at the front are ignored.
-*************************************************************************/
-
-int getfileline(void *vp, char *linebuf, int linebuf_size)
-{
- /* Static buffers we will return. */
- FILE *fp = (FILE *)vp;
- unsigned char c;
- unsigned char *p;
- size_t linebuf_len;
-
- if (fp == NULL) {
- DEBUG(0,("getfileline: Bad file pointer.\n"));
- return -1;
- }
-
- /*
- * Scan the file, a line at a time.
- */
- while (!feof(fp)) {
- linebuf[0] = '\0';
-
- fgets(linebuf, linebuf_size, fp);
- if (ferror(fp)) {
- return -1;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
-
- linebuf_len = strlen(linebuf);
- if (linebuf_len == 0) {
- linebuf[0] = '\0';
- return 0;
- }
-
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n') {
- break;
- }
- }
- } else {
- linebuf[linebuf_len - 1] = '\0';
- }
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
-#endif
- if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("getfileline: end of file reached\n"));
- return 0;
- }
-
- if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("getfileline: skipping comment or blank line\n"));
- continue;
- }
-
- p = (unsigned char *) strchr_m(linebuf, ':');
- if (p == NULL) {
- DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
- continue;
- }
- return linebuf_len;
- }
- return -1;
-}
-
/****************************************************************************
Read a line from a file with possible \ continuation chars.
Blanks at the start or end of a line are stripped.
@@ -353,7 +118,7 @@ char *file_pload(char *syscmd, size_t *size)
total = 0;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
- p = SMB_REALLOC(p, total + n + 1);
+ p = (char *)SMB_REALLOC(p, total + n + 1);
if (!p) {
DEBUG(0,("file_pload: failed to expand buffer!\n"));
close(fd);
@@ -520,9 +285,6 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
return NULL;
}
memset(ret, 0, sizeof(ret[0])*(i+2));
- if (numlines) {
- *numlines = i;
- }
ret[0] = p;
for (s = p, i=0; s < p+size; s++) {
@@ -536,6 +298,15 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
}
}
+ /* remove any blank lines at the end */
+ while (i > 0 && ret[i-1][0] == 0) {
+ i--;
+ }
+
+ if (numlines) {
+ *numlines = i;
+ }
+
return ret;
}
diff --git a/source/lib/util_pw.c b/source/lib/util_pw.c
index 754899f420e..dc184233a6d 100644
--- a/source/lib/util_pw.c
+++ b/source/lib/util_pw.c
@@ -74,7 +74,7 @@ struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
if ((pwnam_cache[i] != NULL) &&
(strcmp(name, pwnam_cache[i]->pw_name) == 0)) {
DEBUG(10, ("Got %s from pwnam_cache\n", name));
- return talloc_reference(mem_ctx, pwnam_cache[i]);
+ return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]);
}
}
@@ -103,7 +103,7 @@ struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
pwnam_cache[i] = tcopy_passwd(pwnam_cache, temp);
if (pwnam_cache[i]!= NULL && mem_ctx != NULL) {
- return talloc_reference(mem_ctx, pwnam_cache[i]);
+ return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]);
}
return tcopy_passwd(NULL, pwnam_cache[i]);
diff --git a/source/lib/util_seaccess.c b/source/lib/util_seaccess.c
index 73fc45c844d..7d14ed896f6 100644
--- a/source/lib/util_seaccess.c
+++ b/source/lib/util_seaccess.c
@@ -31,7 +31,7 @@ extern NT_USER_TOKEN anonymous_token;
static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired,
NTSTATUS *status)
{
- uint32 mask = ace->info.mask;
+ uint32 mask = ace->access_mask;
/*
* Inherit only is ignored.
@@ -97,8 +97,8 @@ static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32
size_t i;
for ( i = 0 ; i < the_acl->num_aces; i++) {
- SEC_ACE *ace = &the_acl->ace[i];
- uint32 mask = ace->info.mask;
+ SEC_ACE *ace = &the_acl->aces[i];
+ uint32 mask = ace->access_mask;
if (!token_sid_in_ace( token, ace))
continue;
@@ -281,12 +281,12 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token,
}
for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
- SEC_ACE *ace = &the_acl->ace[i];
+ SEC_ACE *ace = &the_acl->aces[i];
DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
(unsigned int)i, ace->type, ace->flags,
sid_to_string(sid_str, &ace->trustee),
- (unsigned int) ace->info.mask,
+ (unsigned int) ace->access_mask,
(unsigned int)tmp_acc_desired ));
tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
diff --git a/source/lib/util_sec.c b/source/lib/util_sec.c
index 3f8cb690cd0..3d997ee76ac 100644
--- a/source/lib/util_sec.c
+++ b/source/lib/util_sec.c
@@ -198,7 +198,13 @@ void set_effective_uid(uid_t uid)
{
#if USE_SETRESUID
/* Set the effective as well as the real uid. */
- setresuid(uid,uid,-1);
+ if (setresuid(uid,uid,-1) == -1) {
+ if (errno == EAGAIN) {
+ DEBUG(0, ("setresuid failed with EAGAIN. uid(%d) "
+ "might be over its NPROC limit\n",
+ (int)uid));
+ }
+ }
#endif
#if USE_SETREUID
diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c
index 09fe30f81bb..032be9aa93b 100644
--- a/source/lib/util_sid.c
+++ b/source/lib/util_sid.c
@@ -110,7 +110,7 @@ NT_USER_TOKEN system_token = { 1, system_sid_array, SE_ALL_PRIVS };
****************************************************************************/
static const struct {
- enum SID_NAME_USE sid_type;
+ enum lsa_SidType sid_type;
const char *string;
} sid_name_type[] = {
{SID_NAME_USER, "User"},
@@ -123,7 +123,7 @@ static const struct {
{SID_NAME_UNKNOWN, "UNKNOWN"},
{SID_NAME_COMPUTER, "Computer"},
- {(enum SID_NAME_USE)0, NULL}
+ {(enum lsa_SidType)0, NULL}
};
const char *sid_type_lookup(uint32 sid_type)
@@ -531,7 +531,7 @@ char *sid_binstring(const DOM_SID *sid)
{
char *buf, *s;
int len = sid_size(sid);
- buf = SMB_MALLOC(len);
+ buf = (char *)SMB_MALLOC(len);
if (!buf)
return NULL;
sid_linearize(buf, len, sid);
@@ -549,7 +549,7 @@ char *sid_binstring_hex(const DOM_SID *sid)
{
char *buf, *s;
int len = sid_size(sid);
- buf = SMB_MALLOC(len);
+ buf = (char *)SMB_MALLOC(len);
if (!buf)
return NULL;
sid_linearize(buf, len, sid);
@@ -580,24 +580,20 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
Add SID to an array SIDs
********************************************************************/
-void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+BOOL add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
DOM_SID **sids, size_t *num)
{
- if (mem_ctx != NULL) {
- *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID,
+ *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;
+ *num = 0;
+ return False;
}
sid_copy(&((*sids)[*num]), sid);
*num += 1;
- return;
+ return True;
}
@@ -605,17 +601,17 @@ void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
Add SID to an array SIDs ensuring that it is not already there
********************************************************************/
-void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+BOOL add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
DOM_SID **sids, size_t *num_sids)
{
size_t i;
for (i=0; i<(*num_sids); i++) {
if (sid_compare(sid, &(*sids)[i]) == 0)
- return;
+ return True;
}
- add_sid_to_array(mem_ctx, sid, sids, num_sids);
+ return add_sid_to_array(mem_ctx, sid, sids, num_sids);
}
/********************************************************************
@@ -647,23 +643,26 @@ void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num)
return;
}
-void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
+BOOL add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
uint32 rid, uint32 **pp_rids, size_t *p_num)
{
size_t i;
for (i=0; i<*p_num; i++) {
if ((*pp_rids)[i] == rid)
- return;
+ return True;
}
*pp_rids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_rids, uint32, *p_num+1);
- if (*pp_rids == NULL)
- return;
+ if (*pp_rids == NULL) {
+ *p_num = 0;
+ return False;
+ }
(*pp_rids)[*p_num] = rid;
*p_num += 1;
+ return True;
}
BOOL is_null_sid(const DOM_SID *sid)
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 1a73a310b62..2866a443d47 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -974,7 +974,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
}
if (errno == EINPROGRESS || errno == EALREADY ||
- errno == EAGAIN) {
+ errno == EAGAIN || errno == EINTR) {
/* These are the error messages that something is
progressing. */
good_connect = True;
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index c106c4433aa..ccf0af8b623 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -5,6 +5,7 @@
Copyright (C) Andrew Tridgell 1992-2001
Copyright (C) Simo Sorce 2001-2002
Copyright (C) Martin Pool 2003
+ Copyright (C) James Peach 2006
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,13 +30,18 @@
**/
/**
- * Get the next token from a string, return False if none found.
- * Handles double-quotes.
- *
+ * Internal function to get the next token from a string, return False if none
+ * found. Handles double-quotes. This is the work horse function called by
+ * next_token() and next_token_no_ltrim().
+ *
* Based on a routine by GJC@VILLAGE.COM.
* Extensively modified by Andrew.Tridgell@anu.edu.au
- **/
-BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
+ */
+static BOOL next_token_internal(const char **ptr,
+ char *buff,
+ const char *sep,
+ size_t bufsize,
+ BOOL ltrim)
{
char *s;
char *pbuf;
@@ -51,9 +57,11 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
if (!sep)
sep = " \t\n\r";
- /* find the first non sep char */
- while (*s && strchr_m(sep,*s))
- s++;
+ /* find the first non sep char, if left-trimming is requested */
+ if (ltrim) {
+ while (*s && strchr_m(sep,*s))
+ s++;
+ }
/* nothing left? */
if (! *s)
@@ -76,6 +84,29 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
return(True);
}
+/*
+ * Get the next token from a string, return False if none found. Handles
+ * double-quotes. This version trims leading separator characters before
+ * looking for a token.
+ */
+BOOL next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
+{
+ return next_token_internal(ptr, buff, sep, bufsize, True);
+}
+
+/*
+ * Get the next token from a string, return False if none found. Handles
+ * double-quotes. This version does not trim leading separator characters
+ * before looking for a token.
+ */
+BOOL next_token_no_ltrim(const char **ptr,
+ char *buff,
+ const char *sep,
+ size_t bufsize)
+{
+ return next_token_internal(ptr, buff, sep, bufsize, False);
+}
+
/**
This is like next_token but is not re-entrant and "remembers" the first
parameter so you can pass NULL. This is useful for user interface code
@@ -1043,7 +1074,7 @@ char *realloc_string_sub(char *string, const char *pattern,
while ((p = strstr_m(s,pattern))) {
if (ld > 0) {
int offset = PTR_DIFF(s,string);
- string = SMB_REALLOC(string, ls + ld + 1);
+ string = (char *)SMB_REALLOC(string, ls + ld + 1);
if (!string) {
DEBUG(0, ("realloc_string_sub: out of memory!\n"));
SAFE_FREE(in);
@@ -1112,7 +1143,8 @@ char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src,
while ((p = strstr_m(s,pattern))) {
if (ld > 0) {
int offset = PTR_DIFF(s,string);
- string = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1);
+ string = (char *)TALLOC_REALLOC(mem_ctx, string,
+ ls + ld + 1);
if (!string) {
DEBUG(0, ("talloc_string_sub: out of "
"memory!\n"));
@@ -1561,6 +1593,76 @@ void strupper_m(char *s)
}
/**
+ Count the number of UCS2 characters in a string. Normally this will
+ be the same as the number of bytes in a string for single byte strings,
+ but will be different for multibyte.
+**/
+
+size_t strlen_m(const char *s)
+{
+ size_t count = 0;
+
+ if (!s) {
+ return 0;
+ }
+
+ while (*s && !(((uint8_t)*s) & 0x80)) {
+ s++;
+ count++;
+ }
+
+ if (!*s) {
+ return count;
+ }
+
+ while (*s) {
+ size_t c_size;
+ codepoint_t c = next_codepoint(s, &c_size);
+ if (c < 0x10000) {
+ /* Unicode char fits into 16 bits. */
+ count += 1;
+ } else {
+ /* Double-width unicode char - 32 bits. */
+ count += 2;
+ }
+ s += c_size;
+ }
+
+ return count;
+}
+
+/**
+ Count the number of UCS2 characters in a string including the null
+ terminator.
+**/
+
+size_t strlen_m_term(const char *s)
+{
+ if (!s) {
+ return 0;
+ }
+ return strlen_m(s) + 1;
+}
+
+/*
+ * Weird helper routine for the winreg pipe: If nothing is around, return 0,
+ * if a string is there, include the terminator.
+ */
+
+size_t strlen_m_term_null(const char *s)
+{
+ size_t len;
+ if (!s) {
+ return 0;
+ }
+ len = strlen_m(s);
+ if (len == 0) {
+ return 0;
+ }
+
+ return len+1;
+}
+/**
Return a RFC2254 binary string representation of a buffer.
Used in LDAP filters.
Caller must free.
@@ -1571,7 +1673,7 @@ char *binary_string_rfc2254(char *buf, int len)
char *s;
int i, j;
const char *hex = "0123456789ABCDEF";
- s = SMB_MALLOC(len * 3 + 1);
+ s = (char *)SMB_MALLOC(len * 3 + 1);
if (!s)
return NULL;
for (j=i=0;i<len;i++) {
@@ -1589,7 +1691,7 @@ char *binary_string(char *buf, int len)
char *s;
int i, j;
const char *hex = "0123456789ABCDEF";
- s = SMB_MALLOC(len * 2 + 1);
+ s = (char *)SMB_MALLOC(len * 2 + 1);
if (!s)
return NULL;
for (j=i=0;i<len;i++) {
@@ -1631,49 +1733,6 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
return ret;
}
-
-#if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP)
-/**
- Some platforms don't have strndup.
-**/
-#if defined(PARANOID_MALLOC_CHECKER)
-#undef strndup
-#endif
-
- char *strndup(const char *s, size_t n)
-{
- char *ret;
-
- n = strnlen(s, n);
- ret = SMB_MALLOC(n+1);
- if (!ret)
- return NULL;
- memcpy(ret, s, n);
- ret[n] = 0;
-
- return ret;
-}
-
-#if defined(PARANOID_MALLOC_CHECKER)
-#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
-#endif
-
-#endif
-
-#if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN)
-/**
- Some platforms don't have strnlen
-**/
-
- size_t strnlen(const char *s, size_t n)
-{
- size_t i;
- for (i=0; i<n && s[i] != '\0'; i++)
- /* noop */ ;
- return i;
-}
-#endif
-
/**
List of Strings manipulation functions
**/
@@ -1884,13 +1943,14 @@ int str_list_count( const char **list )
for the work
*****************************************************************************/
-BOOL str_list_sub_basic( char **list, const char *smb_name )
+BOOL str_list_sub_basic( char **list, const char *smb_name,
+ const char *domain_name )
{
char *s, *tmpstr;
while ( *list ) {
s = *list;
- tmpstr = alloc_sub_basic(smb_name, s);
+ tmpstr = alloc_sub_basic(smb_name, domain_name, s);
if ( !tmpstr ) {
DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
return False;
@@ -2210,7 +2270,7 @@ char * base64_encode_data_blob(DATA_BLOB data)
out_cnt = 0;
len = data.length;
output_len = data.length * 2;
- result = SMB_MALLOC(output_len); /* get us plenty of space */
+ result = (char *)SMB_MALLOC(output_len); /* get us plenty of space */
while (len-- && out_cnt < (data.length * 2) - 5) {
int c = (unsigned char) *(data.data++);
@@ -2274,16 +2334,83 @@ SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
return val;
}
+/* Convert a size specification to a count of bytes. We accept the following
+ * suffixes:
+ * bytes if there is no suffix
+ * kK kibibytes
+ * mM mebibytes
+ * gG gibibytes
+ * tT tibibytes
+ * pP whatever the ISO name for petabytes is
+ *
+ * Returns 0 if the string can't be converted.
+ */
+SMB_OFF_T conv_str_size(const char * str)
+{
+ SMB_OFF_T lval;
+ char * end;
+
+ if (str == NULL || *str == '\0') {
+ return 0;
+ }
+
+#ifdef HAVE_STRTOULL
+ if (sizeof(SMB_OFF_T) == 8) {
+ lval = strtoull(str, &end, 10 /* base */);
+ } else {
+ lval = strtoul(str, &end, 10 /* base */);
+ }
+#else
+ lval = strtoul(str, &end, 10 /* base */);
+#endif
+
+ if (end == NULL || end == str) {
+ return 0;
+ }
+
+ if (*end) {
+ SMB_OFF_T lval_orig = lval;
+
+ if (strwicmp(end, "K") == 0) {
+ lval *= (SMB_OFF_T)1024;
+ } else if (strwicmp(end, "M") == 0) {
+ lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
+ } else if (strwicmp(end, "G") == 0) {
+ lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+ (SMB_OFF_T)1024);
+ } else if (strwicmp(end, "T") == 0) {
+ lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+ (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
+ } else if (strwicmp(end, "P") == 0) {
+ lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+ (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
+ (SMB_OFF_T)1024);
+ } else {
+ return 0;
+ }
+
+ /* Primitive attempt to detect wrapping on platforms with
+ * 4-byte SMB_OFF_T. It's better to let the caller handle
+ * a failure than some random number.
+ */
+ if (lval_orig <= lval) {
+ return 0;
+ }
+ }
+
+ return lval;
+}
+
void string_append(char **left, const char *right)
{
int new_len = strlen(right) + 1;
if (*left == NULL) {
- *left = SMB_MALLOC(new_len);
+ *left = (char *)SMB_MALLOC(new_len);
*left[0] = '\0';
} else {
new_len += strlen(*left);
- *left = SMB_REALLOC(*left, new_len);
+ *left = (char *)SMB_REALLOC(*left, new_len);
}
if (*left == NULL) {
@@ -2301,8 +2428,10 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
*strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings, const char *, (*num)+1);
- if ((*strings == NULL) || (dup_str == NULL))
+ if ((*strings == NULL) || (dup_str == NULL)) {
+ *num = 0;
return False;
+ }
(*strings)[*num] = dup_str;
*num += 1;
@@ -2329,11 +2458,7 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
if (*bufsize == 0)
*bufsize = 128;
- if (mem_ctx != NULL)
- *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
- else
- *string = SMB_MALLOC_ARRAY(char, *bufsize);
-
+ *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
if (*string == NULL)
goto error;
}
@@ -2355,13 +2480,8 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
}
if (increased) {
- if (mem_ctx != NULL) {
- *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
- *bufsize);
- } else {
- *string = SMB_REALLOC_ARRAY(*string, char, *bufsize);
- }
-
+ *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
+ *bufsize);
if (*string == NULL) {
goto error;
}
@@ -2374,9 +2494,6 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
error:
*len = -1;
- if (mem_ctx == NULL) {
- SAFE_FREE(*string);
- }
*string = NULL;
}
@@ -2426,3 +2543,52 @@ BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len
return True;
}
+
+/**
+return the number of bytes occupied by a buffer in ASCII format
+the result includes the null termination
+limited by 'n' bytes
+**/
+size_t ascii_len_n(const char *src, size_t n)
+{
+ size_t len;
+
+ len = strnlen(src, n);
+ if (len+1 <= n) {
+ len += 1;
+ }
+
+ return len;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+**/
+size_t utf16_len(const void *buf)
+{
+ size_t len;
+
+ for (len = 0; SVAL(buf,len); len += 2) ;
+
+ return len + 2;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+limited by 'n' bytes
+**/
+size_t utf16_len_n(const void *src, size_t n)
+{
+ size_t len;
+
+ for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
+
+ if (len+2 <= n) {
+ len += 2;
+ }
+
+ return len;
+}
+
diff --git a/source/tdb/tdbutil.c b/source/lib/util_tdb.c
index fc45fa93606..9136e2d6c1e 100644
--- a/source/tdb/tdbutil.c
+++ b/source/lib/util_tdb.c
@@ -20,7 +20,22 @@
*/
#include "includes.h"
-#include <fnmatch.h>
+#undef malloc
+#undef realloc
+#undef calloc
+#undef strdup
+
+/***************************************************************
+ Allow a caller to set a "alarm" flag that tdb can check to abort
+ a blocking lock on SIGALRM.
+***************************************************************/
+
+static sig_atomic_t *palarm_fired;
+
+static void tdb_set_lock_alarm(sig_atomic_t *palarm)
+{
+ palarm_fired = palarm;
+}
/* these are little tdb utility functions that are meant to make
dealing with a tdb database a little less cumbersome in Samba */
@@ -79,7 +94,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key,
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
if (gotalarm) {
DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
- timeout, key.dptr, tdb->name ));
+ timeout, key.dptr, tdb_name(tdb)));
/* TODO: If we time out waiting for a lock, it might
* be nice to use F_GETLK to get the pid of the
* process currently holding the lock and print that
@@ -197,7 +212,7 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int
int32 v_store;
SIVAL(&v_store,0,v);
- data.dptr = (void *)&v_store;
+ data.dptr = (char *)&v_store;
data.dsize = sizeof(int32);
return tdb_store(tdb, key, data, TDB_REPLACE);
@@ -257,7 +272,7 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, u
BOOL ret = True;
SIVAL(&v_store, 0, value);
- data.dptr = (void *)&v_store;
+ data.dptr = (char *)&v_store;
data.dsize = sizeof(uint32);
if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
@@ -641,134 +656,11 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
}
-/**
- * Pack SID passed by pointer
- *
- * @param pack_buf pointer to buffer which is to be filled with packed data
- * @param bufsize size of packing buffer
- * @param sid pointer to sid to be packed
- *
- * @return length of the packed representation of the whole structure
- **/
-size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
-{
- int idx;
- size_t len = 0;
-
- if (!sid || !pack_buf) return -1;
-
- len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
- sid->num_auths);
-
- for (idx = 0; idx < 6; idx++) {
- len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]);
- }
-
- for (idx = 0; idx < MAXSUBAUTHS; idx++) {
- len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]);
- }
-
- return len;
-}
-
-
-/**
- * Unpack SID into a pointer
- *
- * @param pack_buf pointer to buffer with packed representation
- * @param bufsize size of the buffer
- * @param sid pointer to sid structure to be filled with unpacked data
- *
- * @return size of structure unpacked from buffer
- **/
-size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
-{
- int idx, len = 0;
-
- if (!sid || !pack_buf) return -1;
-
- len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
- &sid->sid_rev_num, &sid->num_auths);
-
- for (idx = 0; idx < 6; idx++) {
- len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
- }
-
- for (idx = 0; idx < MAXSUBAUTHS; idx++) {
- len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
- }
-
- return len;
-}
-
-
-/**
- * Pack TRUSTED_DOM_PASS passed by pointer
- *
- * @param pack_buf pointer to buffer which is to be filled with packed data
- * @param bufsize size of the buffer
- * @param pass pointer to trusted domain password to be packed
- *
- * @return length of the packed representation of the whole structure
- **/
-size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
-{
- int idx, len = 0;
-
- if (!pack_buf || !pass) return -1;
-
- /* packing unicode domain name and password */
- len += tdb_pack(pack_buf + len, bufsize - len, "d", pass->uni_name_len);
-
- for (idx = 0; idx < 32; idx++)
- len += tdb_pack(pack_buf + len, bufsize - len, "w", pass->uni_name[idx]);
-
- len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len,
- pass->pass, pass->mod_time);
-
- /* packing SID structure */
- len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid);
-
- return len;
-}
-
-
-/**
- * Unpack TRUSTED_DOM_PASS passed by pointer
- *
- * @param pack_buf pointer to buffer with packed representation
- * @param bufsize size of the buffer
- * @param pass pointer to trusted domain password to be filled with unpacked data
- *
- * @return size of structure unpacked from buffer
- **/
-size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
-{
- int idx, len = 0;
-
- if (!pack_buf || !pass) return -1;
-
- /* unpack unicode domain name and plaintext password */
- len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
-
- for (idx = 0; idx < 32; idx++)
- len += tdb_unpack(pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]);
-
- len += tdb_unpack(pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass,
- &pass->mod_time);
-
- /* unpack domain sid */
- len += tdb_sid_unpack(pack_buf + len, bufsize - len, &pass->domain_sid);
-
- return len;
-}
-
-
/****************************************************************************
Log tdb messages via DEBUG().
****************************************************************************/
-static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
+static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...)
{
va_list ap;
char *ptr = NULL;
@@ -780,7 +672,7 @@ static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
if (!ptr || !*ptr)
return;
- DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
+ DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr));
SAFE_FREE(ptr);
}
@@ -793,12 +685,16 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
{
TDB_CONTEXT *tdb;
+ struct tdb_logging_context log_ctx;
if (!lp_use_mmap())
tdb_flags |= TDB_NOMMAP;
+ log_ctx.log_fn = tdb_log;
+ log_ctx.log_private = NULL;
+
tdb = tdb_open_ex(name, hash_size, tdb_flags,
- open_flags, mode, tdb_log, NULL);
+ open_flags, mode, &log_ctx, NULL);
if (!tdb)
return NULL;
@@ -806,15 +702,6 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
}
/****************************************************************************
- return the name of the current tdb file useful for external logging
- functions
-****************************************************************************/
-const char *tdb_name(struct tdb_context *tdb)
-{
- return tdb->name;
-}
-
-/****************************************************************************
Allow tdb_delete to be used as a tdb_traversal_fn.
****************************************************************************/
@@ -840,7 +727,6 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
TDB_DATA key, next;
TDB_LIST_NODE *list = NULL;
TDB_LIST_NODE *rec = NULL;
- TDB_LIST_NODE *tmp = NULL;
for (key = tdb_firstkey(tdb); key.dptr; key = next) {
/* duplicate key string to ensure null-termination */
@@ -861,7 +747,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
rec->node_key = key;
- DLIST_ADD_END(list, rec, tmp);
+ DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
} else {
@@ -893,3 +779,160 @@ void tdb_search_list_free(TDB_LIST_NODE* node)
node = next_node;
};
}
+
+/****************************************************************************
+ tdb_store, wrapped in a transaction. This way we make sure that a process
+ that dies within writing does not leave a corrupt tdb behind.
+****************************************************************************/
+
+int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+ int flag)
+{
+ int res;
+
+ if ((res = tdb_transaction_start(tdb)) != 0) {
+ DEBUG(5, ("tdb_transaction_start failed\n"));
+ return res;
+ }
+
+ if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) {
+ DEBUG(10, ("tdb_store failed\n"));
+ if (tdb_transaction_cancel(tdb) != 0) {
+ smb_panic("Cancelling transaction failed\n");
+ }
+ return res;
+ }
+
+ if ((res = tdb_transaction_commit(tdb)) != 0) {
+ DEBUG(5, ("tdb_transaction_commit failed\n"));
+ }
+
+ return res;
+}
+
+/****************************************************************************
+ tdb_delete, wrapped in a transaction. This way we make sure that a process
+ that dies within deleting does not leave a corrupt tdb behind.
+****************************************************************************/
+
+int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key)
+{
+ int res;
+
+ if ((res = tdb_transaction_start(tdb)) != 0) {
+ DEBUG(5, ("tdb_transaction_start failed\n"));
+ return res;
+ }
+
+ if ((res = tdb_delete(tdb, key)) != 0) {
+ DEBUG(10, ("tdb_delete failed\n"));
+ if (tdb_transaction_cancel(tdb) != 0) {
+ smb_panic("Cancelling transaction failed\n");
+ }
+ return res;
+ }
+
+ if ((res = tdb_transaction_commit(tdb)) != 0) {
+ DEBUG(5, ("tdb_transaction_commit failed\n"));
+ }
+
+ return res;
+}
+
+/*
+ Log tdb messages via DEBUG().
+*/
+static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
+ const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+
+static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
+ const char *format, ...)
+{
+ va_list ap;
+ char *ptr = NULL;
+ int debuglevel = 0;
+
+ va_start(ap, format);
+ vasprintf(&ptr, format, ap);
+ va_end(ap);
+
+ switch (level) {
+ case TDB_DEBUG_FATAL:
+ debug_level = 0;
+ break;
+ case TDB_DEBUG_ERROR:
+ debuglevel = 1;
+ break;
+ case TDB_DEBUG_WARNING:
+ debuglevel = 2;
+ break;
+ case TDB_DEBUG_TRACE:
+ debuglevel = 5;
+ break;
+ default:
+ debuglevel = 0;
+ }
+
+ if (ptr != NULL) {
+ const char *name = tdb_name(tdb);
+ DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr));
+ free(ptr);
+ }
+}
+
+static struct tdb_wrap *tdb_list;
+
+/* destroy the last connection to a tdb */
+static int tdb_wrap_destructor(struct tdb_wrap *w)
+{
+ tdb_close(w->tdb);
+ DLIST_REMOVE(tdb_list, w);
+ return 0;
+}
+
+/*
+ wrapped connection to a tdb database
+ to close just talloc_free() the tdb_wrap pointer
+ */
+struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
+ const char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode)
+{
+ struct tdb_wrap *w;
+ struct tdb_logging_context log_ctx;
+ log_ctx.log_fn = tdb_wrap_log;
+
+ for (w=tdb_list;w;w=w->next) {
+ if (strcmp(name, w->name) == 0) {
+ /*
+ * Yes, talloc_reference is exactly what we want
+ * here. Otherwise we would have to implement our own
+ * reference counting.
+ */
+ return talloc_reference(mem_ctx, w);
+ }
+ }
+
+ w = talloc(mem_ctx, struct tdb_wrap);
+ if (w == NULL) {
+ return NULL;
+ }
+
+ if (!(w->name = talloc_strdup(w, name))) {
+ talloc_free(w);
+ return NULL;
+ }
+
+ w->tdb = tdb_open_ex(name, hash_size, tdb_flags,
+ open_flags, mode, &log_ctx, NULL);
+ if (w->tdb == NULL) {
+ talloc_free(w);
+ return NULL;
+ }
+
+ talloc_set_destructor(w, tdb_wrap_destructor);
+
+ DLIST_ADD(tdb_list, w);
+
+ return w;
+}
diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c
index a0015c265fb..cf040a2dfc0 100644
--- a/source/lib/util_unistr.c
+++ b/source/lib/util_unistr.c
@@ -88,10 +88,12 @@ void load_case_tables(void)
}
initialised = 1;
- upcase_table = map_file(lib_path("upcase.dat"), 0x20000);
+ upcase_table = (smb_ucs2_t *)map_file(lib_path("upcase.dat"),
+ 0x20000);
upcase_table_use_unmap = ( upcase_table != NULL );
- lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000);
+ lowcase_table = (smb_ucs2_t *)map_file(lib_path("lowcase.dat"),
+ 0x20000);
lowcase_table_use_unmap = ( lowcase_table != NULL );
#ifdef HAVE_SETLOCALE
@@ -111,7 +113,7 @@ void load_case_tables(void)
not available */
if (!upcase_table) {
DEBUG(1,("creating lame upcase table\n"));
- upcase_table = SMB_MALLOC(0x20000);
+ upcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
for (i=0;i<0x10000;i++) {
smb_ucs2_t v;
SSVAL(&v, 0, i);
@@ -126,7 +128,7 @@ void load_case_tables(void)
if (!lowcase_table) {
DEBUG(1,("creating lame lowcase table\n"));
- lowcase_table = SMB_MALLOC(0x20000);
+ lowcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
for (i=0;i<0x10000;i++) {
smb_ucs2_t v;
SSVAL(&v, 0, i);
@@ -169,11 +171,11 @@ static int check_dos_char_slowly(smb_ucs2_t c)
smb_ucs2_t c2 = 0;
int len1, len2;
- len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf),False);
+ len1 = convert_string(CH_UTF16LE, CH_DOS, &c, 2, buf, sizeof(buf),False);
if (len1 == 0) {
return 0;
}
- len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2,False);
+ len2 = convert_string(CH_DOS, CH_UTF16LE, buf, len1, &c2, 2,False);
if (len2 != 2) {
return 0;
}
@@ -228,7 +230,7 @@ void init_valid_table(void)
return;
}
- valid_file = map_file(lib_path("valid.dat"), 0x10000);
+ valid_file = (uint8 *)map_file(lib_path("valid.dat"), 0x10000);
if (valid_file) {
valid_table = valid_file;
mapped_file = 1;
@@ -247,7 +249,7 @@ void init_valid_table(void)
valid_table_use_unmap = False;
DEBUG(2,("creating default valid table\n"));
- valid_table = SMB_MALLOC(0x10000);
+ valid_table = (uint8 *)SMB_MALLOC(0x10000);
for (i=0;i<128;i++) {
valid_table[i] = isalnum(i) || strchr(allowed,i);
}
@@ -482,7 +484,7 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max)
size_t len;
smb_ucs2_t c;
- for(len = 0; *(COPY_UCS2_CHAR(&c,src)) && (len < max); src++, len++) {
+ for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
;
}
diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c
index df70740b33c..6374c2d8a94 100644
--- a/source/lib/util_uuid.c
+++ b/source/lib/util_uuid.c
@@ -27,7 +27,7 @@
#define TIME_OFFSET_HIGH 0x01B21DD2
#define TIME_OFFSET_LOW 0x13814000
-void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr)
+void smb_uuid_pack(const struct GUID uu, UUID_FLAT *ptr)
{
SIVAL(ptr->info, 0, uu.time_low);
SSVAL(ptr->info, 4, uu.time_mid);
@@ -36,7 +36,7 @@ void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr)
memcpy(ptr->info+10, uu.node, 6);
}
-void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu)
+void smb_uuid_unpack(const UUID_FLAT in, struct GUID *uu)
{
uu->time_low = IVAL(in.info, 0);
uu->time_mid = SVAL(in.info, 4);
@@ -45,15 +45,15 @@ void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu)
memcpy(uu->node, in.info+10, 6);
}
-struct uuid smb_uuid_unpack_static(const UUID_FLAT in)
+struct GUID smb_uuid_unpack_static(const UUID_FLAT in)
{
- static struct uuid uu;
+ static struct GUID uu;
smb_uuid_unpack(in, &uu);
return uu;
}
-void smb_uuid_generate_random(struct uuid *uu)
+void smb_uuid_generate_random(struct GUID *uu)
{
UUID_FLAT tmp;
@@ -64,7 +64,7 @@ void smb_uuid_generate_random(struct uuid *uu)
uu->time_hi_and_version = (uu->time_hi_and_version & 0x0FFF) | 0x4000;
}
-char *smb_uuid_to_string(const struct uuid uu)
+char *smb_uuid_to_string(const struct GUID uu)
{
char *out;
@@ -77,7 +77,7 @@ char *smb_uuid_to_string(const struct uuid uu)
return out;
}
-const char *smb_uuid_string_static(const struct uuid uu)
+const char *smb_uuid_string_static(const struct GUID uu)
{
static char out[37];
@@ -90,7 +90,7 @@ const char *smb_uuid_string_static(const struct uuid uu)
return out;
}
-BOOL smb_string_to_uuid(const char *in, struct uuid* uu)
+BOOL smb_string_to_uuid(const char *in, struct GUID* uu)
{
BOOL ret = False;
const char *ptr = in;
diff --git a/source/lib/xfile.c b/source/lib/xfile.c
index 2e90a62df45..8824ca2c3c7 100644
--- a/source/lib/xfile.c
+++ b/source/lib/xfile.c
@@ -80,7 +80,7 @@ static int x_allocate_buffer(XFILE *f)
{
if (f->buf) return 1;
if (f->bufsize == 0) return 0;
- f->buf = SMB_MALLOC(f->bufsize);
+ f->buf = (char *)SMB_MALLOC(f->bufsize);
if (!f->buf) return 0;
f->next = f->buf;
return 1;
diff --git a/source/libaddns/addns.h b/source/libaddns/addns.h
new file mode 100644
index 00000000000..d7774537fe9
--- /dev/null
+++ b/source/libaddns/addns.h
@@ -0,0 +1,32 @@
+/*
+ Public Interface file for Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#ifndef _ADDNS_H
+#define _ADDNS_H
+
+
+#endif /* _ADDNS_H */
+
diff --git a/source/libaddns/dns.h b/source/libaddns/dns.h
new file mode 100644
index 00000000000..6f480a54695
--- /dev/null
+++ b/source/libaddns/dns.h
@@ -0,0 +1,505 @@
+/*
+ Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#ifndef _DNS_H
+#define _DNS_H
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdarg.h>
+
+#ifdef HAVE_UUID_UUID_H
+#include <uuid/uuid.h>
+#endif
+
+#ifdef HAVE_KRB5_H
+#include <krb5.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+
+#ifndef int16
+#define int16 int16_t
+#endif
+
+#ifndef uint16
+#define uint16 uint16_t
+#endif
+
+#ifndef int32
+#define int32 int32_t
+#endif
+
+#ifndef uint32
+#define uint32 uint32_t
+#endif
+#endif
+
+#ifdef HAVE_KRB5_H
+#include <krb5.h>
+#endif
+
+#if HAVE_GSSAPI_H
+#include <gssapi.h>
+#elif HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include <gssapi/gssapi_generic.h>
+#endif
+
+#if defined(HAVE_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
+#define HAVE_GSSAPI_SUPPORT 1
+#endif
+
+#include <talloc.h>
+
+#define TALLOC(ctx, size) talloc_named_const(ctx, size, __location__)
+#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup(ctx, ptr, size, __location__)
+#define TALLOC_ZERO(ctx, size) _talloc_zero(ctx, size, __location__)
+#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define TALLOC_REALLOC(ctx, ptr, count) _talloc_realloc(ctx, ptr, count, __location__)
+#define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)_talloc_realloc_array(ctx, ptr, sizeof(type), count, #type)
+#define TALLOC_FREE(ctx) do { if ((ctx) != NULL) {talloc_free(ctx); ctx=NULL;} } while(0)
+
+/*******************************************************************
+ Type definitions for int16, int32, uint16 and uint32. Needed
+ for Samba coding style
+*******************************************************************/
+
+#ifndef uint8
+# define uint8 unsigned char
+#endif
+
+#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H)
+# if (SIZEOF_SHORT == 4)
+# define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+# else /* SIZEOF_SHORT != 4 */
+# define int16 short
+# endif /* SIZEOF_SHORT != 4 */
+ /* needed to work around compile issue on HP-UX 11.x */
+# define _INT16 1
+#endif
+
+/*
+ * Note we duplicate the size tests in the unsigned
+ * case as int16 may be a typedef from rpc/rpc.h
+ */
+
+#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H)
+# if (SIZEOF_SHORT == 4)
+# define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+# else /* SIZEOF_SHORT != 4 */
+# define uint16 unsigned short
+# endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#if !defined(int32) && !defined(HAVE_INT32_FROM_RPC_RPC_H)
+# if (SIZEOF_INT == 4)
+# define int32 int
+# elif (SIZEOF_LONG == 4)
+# define int32 long
+# elif (SIZEOF_SHORT == 4)
+# define int32 short
+# else
+ /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */
+# define int32 int
+# endif
+ /* needed to work around compile issue on HP-UX 11.x */
+# define _INT32 1
+#endif
+
+/*
+ * Note we duplicate the size tests in the unsigned
+ * case as int32 may be a typedef from rpc/rpc.h
+ */
+
+#if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H)
+# if (SIZEOF_INT == 4)
+# define uint32 unsigned int
+# elif (SIZEOF_LONG == 4)
+# define uint32 unsigned long
+# elif (SIZEOF_SHORT == 4)
+# define uint32 unsigned short
+# else
+ /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */
+# define uint32 unsigned
+# endif
+#endif
+
+/*
+ * check for 8 byte long long
+ */
+
+#if !defined(uint64)
+# if (SIZEOF_LONG == 8)
+# define uint64 unsigned long
+# elif (SIZEOF_LONG_LONG == 8)
+# define uint64 unsigned long long
+# endif /* don't lie. If we don't have it, then don't use it */
+#endif
+
+/* needed on Sun boxes */
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xFFFFFFFF
+#endif
+
+#include "dnserr.h"
+
+
+#define DNS_TCP 1
+#define DNS_UDP 2
+
+#define DNS_OPCODE_UPDATE 1
+
+/* DNS Class Types */
+
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_ANY 255
+#define DNS_CLASS_NONE 254
+
+/* DNS RR Types */
+
+#define DNS_RR_A 1
+
+#define DNS_TCP_PORT 53
+#define DNS_UDP_PORT 53
+
+#define QTYPE_A 1
+#define QTYPE_NS 2
+#define QTYPE_MD 3
+#define QTYPE_CNAME 5
+#define QTYPE_SOA 6
+#define QTYPE_ANY 255
+#define QTYPE_TKEY 249
+#define QTYPE_TSIG 250
+
+/*
+MF 4 a mail forwarder (Obsolete - use MX)
+CNAME 5 the canonical name for an alias
+SOA 6 marks the start of a zone of authority
+MB 7 a mailbox domain name (EXPERIMENTAL)
+MG 8 a mail group member (EXPERIMENTAL)
+MR 9 a mail rename domain name (EXPERIMENTAL)
+NULL 10 a null RR (EXPERIMENTAL)
+WKS 11 a well known service description
+PTR 12 a domain name pointer
+HINFO 13 host information
+MINFO 14 mailbox or mail list information
+MX 15 mail exchange
+TXT 16 text strings
+*/
+
+#define QR_QUERY 0x0000
+#define QR_RESPONSE 0x0001
+
+#define OPCODE_QUERY 0x00
+#define OPCODE_IQUERY 0x01
+#define OPCODE_STATUS 0x02
+
+#define AA 1
+
+#define RECURSION_DESIRED 0x01
+
+#define RCODE_NOERROR 0
+#define RCODE_FORMATERROR 1
+#define RCODE_SERVER_FAILURE 2
+#define RCODE_NAME_ERROR 3
+#define RCODE_NOTIMPLEMENTED 4
+#define RCODE_REFUSED 5
+
+#define SENDBUFFER_SIZE 65536
+#define RECVBUFFER_SIZE 65536
+
+/*
+ * TKEY Modes from rfc2930
+ */
+
+#define DNS_TKEY_MODE_SERVER 1
+#define DNS_TKEY_MODE_DH 2
+#define DNS_TKEY_MODE_GSSAPI 3
+#define DNS_TKEY_MODE_RESOLVER 4
+#define DNS_TKEY_MODE_DELETE 5
+
+
+#define DNS_ONE_DAY_IN_SECS 86400
+#define DNS_TEN_HOURS_IN_SECS 36000
+
+#define SOCKET_ERROR -1
+#define INVALID_SOCKET -1
+
+#define DNS_NO_ERROR 0
+#define DNS_FORMAT_ERROR 1
+#define DNS_SERVER_FAILURE 2
+#define DNS_NAME_ERROR 3
+#define DNS_NOT_IMPLEMENTED 4
+#define DNS_REFUSED 5
+
+typedef long HANDLE;
+
+#ifndef _UPPER_BOOL
+typedef int BOOL;
+#define _UPPER_BOOL
+#endif
+
+
+enum dns_ServerType { DNS_SRV_ANY, DNS_SRV_WIN2000, DNS_SRV_WIN2003 };
+
+struct dns_domain_label {
+ struct dns_domain_label *next;
+ char *label;
+ size_t len;
+};
+
+struct dns_domain_name {
+ struct dns_domain_label *pLabelList;
+};
+
+struct dns_question {
+ struct dns_domain_name *name;
+ uint16 q_type;
+ uint16 q_class;
+};
+
+/*
+ * Before changing the definition of dns_zone, look
+ * dns_marshall_update_request(), we rely on this being the same as
+ * dns_question right now.
+ */
+
+struct dns_zone {
+ struct dns_domain_name *name;
+ uint16 z_type;
+ uint16 z_class;
+};
+
+struct dns_rrec {
+ struct dns_domain_name *name;
+ uint16 type;
+ uint16 r_class;
+ uint32 ttl;
+ uint16 data_length;
+ uint8 *data;
+};
+
+struct dns_tkey_record {
+ struct dns_domain_name *algorithm;
+ time_t inception;
+ time_t expiration;
+ uint16 mode;
+ uint16 error;
+ uint16 key_length;
+ uint8 *key;
+};
+
+struct dns_request {
+ uint16 id;
+ uint16 flags;
+ uint16 num_questions;
+ uint16 num_answers;
+ uint16 num_auths;
+ uint16 num_additionals;
+ struct dns_question **questions;
+ struct dns_rrec **answers;
+ struct dns_rrec **auths;
+ struct dns_rrec **additionals;
+};
+
+/*
+ * Before changing the definition of dns_update_request, look
+ * dns_marshall_update_request(), we rely on this being the same as
+ * dns_request right now.
+ */
+
+struct dns_update_request {
+ uint16 id;
+ uint16 flags;
+ uint16 num_zones;
+ uint16 num_preqs;
+ uint16 num_updates;
+ uint16 num_additionals;
+ struct dns_zone **zones;
+ struct dns_rrec **preqs;
+ struct dns_rrec **updates;
+ struct dns_rrec **additionals;
+};
+
+struct dns_connection {
+ int32 hType;
+ int s;
+ struct sockaddr RecvAddr;
+};
+
+struct dns_buffer {
+ uint8 *data;
+ size_t size;
+ size_t offset;
+ DNS_ERROR error;
+};
+
+/* from dnsutils.c */
+
+DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx,
+ const char *pszDomainName,
+ struct dns_domain_name **presult );
+char *dns_generate_keyname( TALLOC_CTX *mem_ctx );
+
+/* from dnsrecord.c */
+
+DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
+ uint16 q_type, uint16 q_class,
+ struct dns_request **preq );
+DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
+ struct dns_update_request **preq );
+DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
+ const char *host, int num_ips,
+ const struct in_addr *iplist,
+ struct dns_update_request **preq);
+DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
+ uint16 type, uint16 r_class, uint32 ttl,
+ uint16 data_length, uint8 *data,
+ struct dns_rrec **prec);
+DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
+ uint16 *num_records, struct dns_rrec ***records);
+DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
+ const char *algorithm_name, time_t inception,
+ time_t expiration, uint16 mode, uint16 error,
+ uint16 key_length, const uint8 *key,
+ struct dns_rrec **prec);
+DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
+ const char *name,
+ const struct in_addr *ip,
+ struct dns_rrec **prec);
+DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
+ uint16 type, uint16 r_class,
+ struct dns_rrec **prec);
+DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
+ const char *name, uint32 type,
+ struct dns_rrec **prec);
+DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
+ uint32 ttl, struct in_addr ip,
+ struct dns_rrec **prec);
+DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
+ struct dns_tkey_record **ptkey);
+DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
+ const char *algorithm_name,
+ time_t time_signed, uint16 fudge,
+ uint16 mac_length, const uint8 *mac,
+ uint16 original_id, uint16 error,
+ struct dns_rrec **prec);
+DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
+ uint16 *num_records, struct dns_rrec ***records);
+
+/* from dnssock.c */
+
+DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
+ TALLOC_CTX *mem_ctx,
+ struct dns_connection **conn );
+DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf);
+DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
+ struct dns_buffer **presult);
+DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
+ const struct dns_request *req,
+ struct dns_request **resp);
+DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
+ struct dns_connection *conn,
+ struct dns_update_request *up_req,
+ struct dns_update_request **up_resp);
+
+/* from dnsmarshall.c */
+
+struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx);
+void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data,
+ size_t len);
+void dns_marshall_uint16(struct dns_buffer *buf, uint16 val);
+void dns_marshall_uint32(struct dns_buffer *buf, uint32 val);
+void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data,
+ size_t len);
+void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val);
+void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val);
+void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_domain_name **pname);
+void dns_marshall_domain_name(struct dns_buffer *buf,
+ const struct dns_domain_name *name);
+void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_domain_name **pname);
+DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx,
+ const struct dns_request *req,
+ struct dns_buffer **pbuf);
+DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_request **preq);
+DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx,
+ struct dns_update_request *update,
+ struct dns_buffer **pbuf);
+DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_update_request **pupreq);
+struct dns_request *dns_update2request(struct dns_update_request *update);
+struct dns_update_request *dns_request2update(struct dns_request *request);
+uint16 dns_response_code(uint16 flags);
+
+/* from dnsgss.c */
+
+#ifdef HAVE_GSSAPI_SUPPORT
+
+void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat );
+DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
+ const char *servername,
+ const char *keyname,
+ gss_ctx_id_t *gss_ctx,
+ enum dns_ServerType srv_type );
+DNS_ERROR dns_sign_update(struct dns_update_request *req,
+ gss_ctx_id_t gss_ctx,
+ const char *keyname,
+ const char *algorithmname,
+ time_t time_signed, uint16 fudge);
+DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
+ const char *domainname,
+ const char *hostname,
+ const struct in_addr *ip_addr,
+ size_t num_adds,
+ struct dns_update_request **preq);
+
+#endif /* HAVE_GSSAPI_SUPPORT */
+
+#endif /* _DNS_H */
diff --git a/source/libaddns/dnserr.h b/source/libaddns/dnserr.h
new file mode 100644
index 00000000000..c46a9831ccc
--- /dev/null
+++ b/source/libaddns/dnserr.h
@@ -0,0 +1,89 @@
+/*
+ Error codes for Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#ifndef _DNSERR_H
+#define _DNSERR_H
+
+
+/* The Splint code analysis tool (http://www.splint.org.) doesn't
+ like immediate structures. */
+
+#ifdef _SPLINT_
+#undef HAVE_IMMEDIATE_STRUCTURES
+#endif
+
+/* Setup the DNS_ERROR typedef. Technique takes from nt_status.h */
+
+#if defined(HAVE_IMMEDIATE_STRUCTURES)
+typedef struct {uint32 v;} DNS_ERROR;
+#define ERROR_DNS(x) ((DNS_ERROR) { x })
+#define ERROR_DNS_V(x) ((x).v)
+#else
+typedef uint32 DNS_ERROR;
+#define ERROR_DNS(x) (x)
+#define ERROR_DNS_V(x) (x)
+#endif
+
+#define ERR_DNS_IS_OK(x) (ERROR_DNS_V(x) == 0)
+#define ERR_DNS_EQUAL(x,y) (ERROR_DNS_V(x) == ERROR_DNS_V(y))
+
+/*************************************************
+ * Define the error codes here
+ *************************************************/
+
+#define ERROR_DNS_SUCCESS ERROR_DNS(0)
+#define ERROR_DNS_RECORD_NOT_FOUND ERROR_DNS(1)
+#define ERROR_DNS_BAD_RESPONSE ERROR_DNS(2)
+#define ERROR_DNS_INVALID_PARAMETER ERROR_DNS(3)
+#define ERROR_DNS_NO_MEMORY ERROR_DNS(4)
+#define ERROR_DNS_INVALID_NAME_SERVER ERROR_DNS(5)
+#define ERROR_DNS_CONNECTION_FAILED ERROR_DNS(6)
+#define ERROR_DNS_GSS_ERROR ERROR_DNS(7)
+#define ERROR_DNS_INVALID_NAME ERROR_DNS(8)
+#define ERROR_DNS_INVALID_MESSAGE ERROR_DNS(9)
+#define ERROR_DNS_SOCKET_ERROR ERROR_DNS(10)
+#define ERROR_DNS_UPDATE_FAILED ERROR_DNS(11)
+
+/*
+ * About to be removed, transitional error
+ */
+#define ERROR_DNS_UNSUCCESSFUL ERROR_DNS(999)
+
+
+#define ERROR_BAD_RESPONSE 1
+#define ERROR_RECORD_NOT_FOUND 2
+#define ERROR_OUTOFMEMORY 8
+#if !defined(ERROR_INVALID_PARAMETER)
+#define ERROR_INVALID_PARAMETER 87
+#endif
+
+/*
+ * About to be removed, transitional error
+ */
+#define ERROR_UNSUCCESSFUL 999
+
+#endif /* _DNSERR_H */
+
diff --git a/source/libaddns/dnsgss.c b/source/libaddns/dnsgss.c
new file mode 100644
index 00000000000..798fd4404ee
--- /dev/null
+++ b/source/libaddns/dnsgss.c
@@ -0,0 +1,344 @@
+/*
+ Public Interface file for Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "dns.h"
+#include <ctype.h>
+
+
+#ifdef HAVE_GSSAPI_SUPPORT
+
+/*********************************************************************
+*********************************************************************/
+
+static int strupr( char *szDomainName )
+{
+ if ( !szDomainName ) {
+ return ( 0 );
+ }
+ while ( *szDomainName != '\0' ) {
+ *szDomainName = toupper( *szDomainName );
+ szDomainName++;
+ }
+ return ( 0 );
+}
+
+#if 0
+/*********************************************************************
+*********************************************************************/
+
+static void display_status_1( const char *m, OM_uint32 code, int type )
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc msg;
+ OM_uint32 msg_ctx;
+
+ msg_ctx = 0;
+ while ( 1 ) {
+ maj_stat = gss_display_status( &min_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg );
+ fprintf( stdout, "GSS-API error %s: %s\n", m,
+ ( char * ) msg.value );
+ ( void ) gss_release_buffer( &min_stat, &msg );
+
+ if ( !msg_ctx )
+ break;
+ }
+}
+
+/*********************************************************************
+*********************************************************************/
+
+void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat )
+{
+ display_status_1( msg, maj_stat, GSS_C_GSS_CODE );
+ display_status_1( msg, min_stat, GSS_C_MECH_CODE );
+}
+#endif
+
+static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
+ struct dns_connection *conn,
+ const char *keyname,
+ const gss_name_t target_name,
+ gss_ctx_id_t *ctx,
+ enum dns_ServerType srv_type )
+{
+ struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc;
+ OM_uint32 major, minor;
+ OM_uint32 ret_flags;
+ DNS_ERROR err;
+
+ gss_OID_desc krb5_oid_desc =
+ { 9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
+
+ *ctx = GSS_C_NO_CONTEXT;
+ input_ptr = NULL;
+
+ do {
+ major = gss_init_sec_context(
+ &minor, NULL, ctx, target_name, &krb5_oid_desc,
+ GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG |
+ GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
+ GSS_C_INTEG_FLAG | GSS_C_DELEG_FLAG,
+ 0, NULL, input_ptr, NULL, &output_desc,
+ &ret_flags, NULL );
+
+ if (input_ptr != NULL) {
+ TALLOC_FREE(input_desc.value);
+ }
+
+ if (output_desc.length != 0) {
+
+ struct dns_request *req;
+ struct dns_rrec *rec;
+ struct dns_buffer *buf;
+
+ time_t t = time(NULL);
+
+ err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY,
+ DNS_CLASS_IN, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_create_tkey_record(
+ req, keyname, "gss.microsoft.com", t,
+ t + 86400, DNS_TKEY_MODE_GSSAPI, 0,
+ output_desc.length, (uint8 *)output_desc.value,
+ &rec );
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ /* Windows 2000 DNS is broken and requires the
+ TKEY payload in the Answer section instead
+ of the Additional seciton like Windows 2003 */
+
+ if ( srv_type == DNS_SRV_WIN2000 ) {
+ err = dns_add_rrec(req, rec, &req->num_answers,
+ &req->answers);
+ } else {
+ err = dns_add_rrec(req, rec, &req->num_additionals,
+ &req->additionals);
+ }
+
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_marshall_request(req, req, &buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_send(conn, buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ TALLOC_FREE(req);
+ }
+
+ gss_release_buffer(&minor, &output_desc);
+
+ if ((major != GSS_S_COMPLETE) &&
+ (major != GSS_S_CONTINUE_NEEDED)) {
+ return ERROR_DNS_GSS_ERROR;
+ }
+
+ if (major == GSS_S_CONTINUE_NEEDED) {
+
+ struct dns_request *resp;
+ struct dns_buffer *buf;
+ struct dns_tkey_record *tkey;
+
+ err = dns_receive(mem_ctx, conn, &buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_unmarshall_request(buf, buf, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ /*
+ * TODO: Compare id and keyname
+ */
+
+ if ((resp->num_additionals != 1) ||
+ (resp->num_answers == 0) ||
+ (resp->answers[0]->type != QTYPE_TKEY)) {
+ err = ERROR_DNS_INVALID_MESSAGE;
+ goto error;
+ }
+
+ err = dns_unmarshall_tkey_record(
+ mem_ctx, resp->answers[0], &tkey);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ input_desc.length = tkey->key_length;
+ input_desc.value = talloc_move(mem_ctx, &tkey->key);
+
+ input_ptr = &input_desc;
+
+ TALLOC_FREE(buf);
+ }
+
+ } while ( major == GSS_S_CONTINUE_NEEDED );
+
+ /* If we arrive here, we have a valid security context */
+
+ err = ERROR_DNS_SUCCESS;
+
+ error:
+
+ return err;
+}
+
+DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
+ const char *servername,
+ const char *keyname,
+ gss_ctx_id_t *gss_ctx,
+ enum dns_ServerType srv_type )
+{
+ OM_uint32 major, minor;
+
+ char *upcaserealm, *targetname;
+ DNS_ERROR err;
+
+ gss_buffer_desc input_name;
+ struct dns_connection *conn;
+
+ gss_name_t targ_name;
+
+ krb5_principal host_principal;
+ krb5_context krb_ctx = NULL;
+
+ gss_OID_desc nt_host_oid_desc =
+ { 10, (char *)"\052\206\110\206\367\022\001\002\002\002" };
+
+ TALLOC_CTX *mem_ctx;
+
+ if (!(mem_ctx = talloc_init("dns_negotiate_sec_ctx"))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_open_connection( servername, DNS_TCP, mem_ctx, &conn );
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (!(upcaserealm = talloc_strdup(mem_ctx, target_realm))) {
+ err = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ strupr(upcaserealm);
+
+ if (!(targetname = talloc_asprintf(mem_ctx, "dns/%s@%s",
+ servername, upcaserealm))) {
+ err = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ krb5_init_context( &krb_ctx );
+ krb5_parse_name( krb_ctx, targetname, &host_principal );
+
+ input_name.value = &host_principal;
+ input_name.length = sizeof( host_principal );
+
+ major = gss_import_name( &minor, &input_name,
+ &nt_host_oid_desc, &targ_name );
+
+ if (major) {
+ krb5_free_principal( krb_ctx, host_principal );
+ krb5_free_context( krb_ctx );
+ err = ERROR_DNS_GSS_ERROR;
+ goto error;
+ }
+
+ err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname,
+ targ_name, gss_ctx, srv_type );
+
+ gss_release_name( &minor, &targ_name );
+ krb5_free_principal( krb_ctx, host_principal );
+ krb5_free_context( krb_ctx );
+
+ error:
+ TALLOC_FREE(mem_ctx);
+
+ return err;
+}
+
+DNS_ERROR dns_sign_update(struct dns_update_request *req,
+ gss_ctx_id_t gss_ctx,
+ const char *keyname,
+ const char *algorithmname,
+ time_t time_signed, uint16 fudge)
+{
+ struct dns_buffer *buf;
+ DNS_ERROR err;
+ struct dns_domain_name *key, *algorithm;
+ struct gss_buffer_desc_struct msg, mic;
+ OM_uint32 major, minor;
+ struct dns_rrec *rec;
+
+ err = dns_marshall_update_request(req, req, &buf);
+ if (!ERR_DNS_IS_OK(err)) return err;
+
+ err = dns_domain_name_from_string(buf, keyname, &key);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_domain_name_from_string(buf, algorithmname, &algorithm);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ dns_marshall_domain_name(buf, key);
+ dns_marshall_uint16(buf, DNS_CLASS_ANY);
+ dns_marshall_uint32(buf, 0); /* TTL */
+ dns_marshall_domain_name(buf, algorithm);
+ dns_marshall_uint16(buf, 0); /* Time prefix for 48-bit time_t */
+ dns_marshall_uint32(buf, time_signed);
+ dns_marshall_uint16(buf, fudge);
+ dns_marshall_uint16(buf, 0); /* error */
+ dns_marshall_uint16(buf, 0); /* other len */
+
+ err = buf->error;
+ if (!ERR_DNS_IS_OK(buf->error)) goto error;
+
+ msg.value = (void *)buf->data;
+ msg.length = buf->offset;
+
+ major = gss_get_mic(&minor, gss_ctx, 0, &msg, &mic);
+ if (major != 0) {
+ err = ERROR_DNS_GSS_ERROR;
+ goto error;
+ }
+
+ if (mic.length > 0xffff) {
+ gss_release_buffer(&minor, &mic);
+ err = ERROR_DNS_GSS_ERROR;
+ goto error;
+ }
+
+ err = dns_create_tsig_record(buf, keyname, algorithmname, time_signed,
+ fudge, mic.length, (uint8 *)mic.value,
+ req->id, 0, &rec);
+ gss_release_buffer(&minor, &mic);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_additionals, &req->additionals);
+
+ error:
+ TALLOC_FREE(buf);
+ return err;
+}
+
+#endif /* HAVE_GSSAPI_SUPPORT */
diff --git a/source/libaddns/dnsmarshall.c b/source/libaddns/dnsmarshall.c
new file mode 100644
index 00000000000..f23504f201a
--- /dev/null
+++ b/source/libaddns/dnsmarshall.c
@@ -0,0 +1,531 @@
+/*
+ Linux DNS client library implementation
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "dns.h"
+#include "assert.h"
+
+struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx)
+{
+ struct dns_buffer *result;
+
+ if (!(result = talloc(mem_ctx, struct dns_buffer))) {
+ return NULL;
+ }
+
+ result->offset = 0;
+ result->error = ERROR_DNS_SUCCESS;
+
+ /*
+ * Small inital size to excercise the realloc code
+ */
+ result->size = 2;
+
+ if (!(result->data = TALLOC_ARRAY(result, uint8, result->size))) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data,
+ size_t len)
+{
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ if (buf->offset + len < buf->offset) {
+ /*
+ * Wraparound!
+ */
+ buf->error = ERROR_DNS_INVALID_PARAMETER;
+ return;
+ }
+
+ if ((buf->offset + len) > 0xffff) {
+ /*
+ * Only 64k possible
+ */
+ buf->error = ERROR_DNS_INVALID_PARAMETER;
+ return;
+ }
+
+ if (buf->offset + len > buf->size) {
+ size_t new_size = buf->offset + len;
+ uint8 *new_data;
+
+ /*
+ * Don't do too many reallocs, round up to some multiple
+ */
+
+ new_size += (64 - (new_size % 64));
+
+ if (!(new_data = TALLOC_REALLOC_ARRAY(buf, buf->data, uint8,
+ new_size))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ return;
+ }
+
+ buf->size = new_size;
+ buf->data = new_data;
+ }
+
+ memcpy(buf->data + buf->offset, data, len);
+ buf->offset += len;
+ return;
+}
+
+void dns_marshall_uint16(struct dns_buffer *buf, uint16 val)
+{
+ uint16 n_val = htons(val);
+ dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
+}
+
+void dns_marshall_uint32(struct dns_buffer *buf, uint32 val)
+{
+ uint32 n_val = htonl(val);
+ dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
+}
+
+void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data,
+ size_t len)
+{
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ if ((len > buf->size) || (buf->offset + len > buf->size)) {
+ buf->error = ERROR_DNS_INVALID_MESSAGE;
+ return;
+ }
+
+ memcpy((void *)data, (const void *)(buf->data + buf->offset), len);
+ buf->offset += len;
+
+ return;
+}
+
+void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val)
+{
+ uint16 n_val;
+
+ dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ *val = ntohs(n_val);
+}
+
+void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val)
+{
+ uint32 n_val;
+
+ dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ *val = ntohl(n_val);
+}
+
+void dns_marshall_domain_name(struct dns_buffer *buf,
+ const struct dns_domain_name *name)
+{
+ struct dns_domain_label *label;
+ char end_char = '\0';
+
+ /*
+ * TODO: Implement DNS compression
+ */
+
+ for (label = name->pLabelList; label != NULL; label = label->next) {
+ uint8 len = label->len;
+
+ dns_marshall_buffer(buf, (uint8 *)&len, sizeof(len));
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ dns_marshall_buffer(buf, (uint8 *)label->label, len);
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+ }
+
+ dns_marshall_buffer(buf, (uint8 *)&end_char, 1);
+}
+
+static void dns_unmarshall_label(TALLOC_CTX *mem_ctx,
+ int level,
+ struct dns_buffer *buf,
+ struct dns_domain_label **plabel)
+{
+ struct dns_domain_label *label;
+ uint8 len;
+
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ if (level > 128) {
+ /*
+ * Protect against recursion
+ */
+ buf->error = ERROR_DNS_INVALID_MESSAGE;
+ return;
+ }
+
+ dns_unmarshall_buffer(buf, &len, sizeof(len));
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ if (len == 0) {
+ *plabel = NULL;
+ return;
+ }
+
+ if ((len & 0xc0) == 0xc0) {
+ /*
+ * We've got a compressed name. Build up a new "fake" buffer
+ * and using the calculated offset.
+ */
+ struct dns_buffer new_buf;
+ uint8 low;
+
+ dns_unmarshall_buffer(buf, &low, sizeof(low));
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ new_buf = *buf;
+ new_buf.offset = len & 0x3f;
+ new_buf.offset <<= 8;
+ new_buf.offset |= low;
+
+ dns_unmarshall_label(mem_ctx, level+1, &new_buf, plabel);
+ buf->error = new_buf.error;
+ return;
+ }
+
+ if ((len & 0xc0) != 0) {
+ buf->error = ERROR_DNS_INVALID_NAME;
+ return;
+ }
+
+ if (!(label = talloc(mem_ctx, struct dns_domain_label))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ return;
+ }
+
+ label->len = len;
+
+ if (!(label->label = TALLOC_ARRAY(label, char, len+1))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ dns_unmarshall_buffer(buf, (uint8 *)label->label, len);
+ if (!ERR_DNS_IS_OK(buf->error)) goto error;
+
+ dns_unmarshall_label(label, level+1, buf, &label->next);
+ if (!ERR_DNS_IS_OK(buf->error)) goto error;
+
+ *plabel = label;
+ return;
+
+ error:
+ TALLOC_FREE(label);
+ return;
+}
+
+void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_domain_name **pname)
+{
+ struct dns_domain_name *name;
+
+ if (!ERR_DNS_IS_OK(buf->error)) return;
+
+ if (!(name = talloc(mem_ctx, struct dns_domain_name))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ }
+
+ dns_unmarshall_label(name, 0, buf, &name->pLabelList);
+
+ if (!ERR_DNS_IS_OK(buf->error)) {
+ return;
+ }
+
+ *pname = name;
+ return;
+}
+
+static void dns_marshall_question(struct dns_buffer *buf,
+ const struct dns_question *q)
+{
+ dns_marshall_domain_name(buf, q->name);
+ dns_marshall_uint16(buf, q->q_type);
+ dns_marshall_uint16(buf, q->q_class);
+}
+
+static void dns_unmarshall_question(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_question **pq)
+{
+ struct dns_question *q;
+
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ if (!(q = talloc(mem_ctx, struct dns_question))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ return;
+ }
+
+ dns_unmarshall_domain_name(q, buf, &q->name);
+ dns_unmarshall_uint16(buf, &q->q_type);
+ dns_unmarshall_uint16(buf, &q->q_class);
+
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ *pq = q;
+}
+
+static void dns_marshall_rr(struct dns_buffer *buf,
+ const struct dns_rrec *r)
+{
+ dns_marshall_domain_name(buf, r->name);
+ dns_marshall_uint16(buf, r->type);
+ dns_marshall_uint16(buf, r->r_class);
+ dns_marshall_uint32(buf, r->ttl);
+ dns_marshall_uint16(buf, r->data_length);
+ dns_marshall_buffer(buf, r->data, r->data_length);
+}
+
+static void dns_unmarshall_rr(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_rrec **pr)
+{
+ struct dns_rrec *r;
+
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ if (!(r = talloc(mem_ctx, struct dns_rrec))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ return;
+ }
+
+ dns_unmarshall_domain_name(r, buf, &r->name);
+ dns_unmarshall_uint16(buf, &r->type);
+ dns_unmarshall_uint16(buf, &r->r_class);
+ dns_unmarshall_uint32(buf, &r->ttl);
+ dns_unmarshall_uint16(buf, &r->data_length);
+ r->data = NULL;
+
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ if (r->data_length != 0) {
+ if (!(r->data = TALLOC_ARRAY(r, uint8, r->data_length))) {
+ buf->error = ERROR_DNS_NO_MEMORY;
+ return;
+ }
+ dns_unmarshall_buffer(buf, r->data, r->data_length);
+ }
+
+ if (!(ERR_DNS_IS_OK(buf->error))) return;
+
+ *pr = r;
+}
+
+DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx,
+ const struct dns_request *req,
+ struct dns_buffer **pbuf)
+{
+ struct dns_buffer *buf;
+ uint16 i;
+
+ if (!(buf = dns_create_buffer(mem_ctx))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ dns_marshall_uint16(buf, req->id);
+ dns_marshall_uint16(buf, req->flags);
+ dns_marshall_uint16(buf, req->num_questions);
+ dns_marshall_uint16(buf, req->num_answers);
+ dns_marshall_uint16(buf, req->num_auths);
+ dns_marshall_uint16(buf, req->num_additionals);
+
+ for (i=0; i<req->num_questions; i++) {
+ dns_marshall_question(buf, req->questions[i]);
+ }
+ for (i=0; i<req->num_answers; i++) {
+ dns_marshall_rr(buf, req->answers[i]);
+ }
+ for (i=0; i<req->num_auths; i++) {
+ dns_marshall_rr(buf, req->auths[i]);
+ }
+ for (i=0; i<req->num_additionals; i++) {
+ dns_marshall_rr(buf, req->additionals[i]);
+ }
+
+ if (!ERR_DNS_IS_OK(buf->error)) {
+ DNS_ERROR err = buf->error;
+ TALLOC_FREE(buf);
+ return err;
+ }
+
+ *pbuf = buf;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_request **preq)
+{
+ struct dns_request *req;
+ uint16 i;
+ DNS_ERROR err;
+
+ if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ dns_unmarshall_uint16(buf, &req->id);
+ dns_unmarshall_uint16(buf, &req->flags);
+ dns_unmarshall_uint16(buf, &req->num_questions);
+ dns_unmarshall_uint16(buf, &req->num_answers);
+ dns_unmarshall_uint16(buf, &req->num_auths);
+ dns_unmarshall_uint16(buf, &req->num_additionals);
+
+ if (!ERR_DNS_IS_OK(buf->error)) goto error;
+
+ err = ERROR_DNS_NO_MEMORY;
+
+ if ((req->num_questions != 0) &&
+ !(req->questions = TALLOC_ARRAY(req, struct dns_question *,
+ req->num_questions))) {
+ goto error;
+ }
+ if ((req->num_answers != 0) &&
+ !(req->answers = TALLOC_ARRAY(req, struct dns_rrec *,
+ req->num_answers))) {
+ goto error;
+ }
+ if ((req->num_auths != 0) &&
+ !(req->auths = TALLOC_ARRAY(req, struct dns_rrec *,
+ req->num_auths))) {
+ goto error;
+ }
+ if ((req->num_additionals != 0) &&
+ !(req->additionals = TALLOC_ARRAY(req, struct dns_rrec *,
+ req->num_additionals))) {
+ goto error;
+ }
+
+ for (i=0; i<req->num_questions; i++) {
+ dns_unmarshall_question(req->questions, buf,
+ &req->questions[i]);
+ }
+ for (i=0; i<req->num_answers; i++) {
+ dns_unmarshall_rr(req->answers, buf,
+ &req->answers[i]);
+ }
+ for (i=0; i<req->num_auths; i++) {
+ dns_unmarshall_rr(req->auths, buf,
+ &req->auths[i]);
+ }
+ for (i=0; i<req->num_additionals; i++) {
+ dns_unmarshall_rr(req->additionals, buf,
+ &req->additionals[i]);
+ }
+
+ if (!ERR_DNS_IS_OK(buf->error)) {
+ err = buf->error;
+ goto error;
+ }
+
+ *preq = req;
+ return ERROR_DNS_SUCCESS;
+
+ error:
+ err = buf->error;
+ TALLOC_FREE(req);
+ return err;
+}
+
+struct dns_request *dns_update2request(struct dns_update_request *update)
+{
+ struct dns_request *req;
+
+ /*
+ * This is a non-specified construct that happens to work on Linux/gcc
+ * and I would expect it to work everywhere else. dns_request and
+ * dns_update_request are essentially the same structures with
+ * different names, so any difference would mean that the compiler
+ * applied two different variations of padding given the same types in
+ * the structures.
+ */
+
+ req = (struct dns_request *)(void *)update;
+
+ /*
+ * The assert statement here looks like we could do the equivalent
+ * assignments to get portable, but it would mean that we have to
+ * allocate the dns_question record for the dns_zone records. We
+ * assume that if this assert works then the same holds true for
+ * dns_zone<>dns_question as well.
+ */
+
+#ifdef DEVELOPER
+ assert((req->id == update->id) && (req->flags == update->flags) &&
+ (req->num_questions == update->num_zones) &&
+ (req->num_answers == update->num_preqs) &&
+ (req->num_auths == update->num_updates) &&
+ (req->num_additionals == update->num_additionals) &&
+ (req->questions ==
+ (struct dns_question **)(void *)update->zones) &&
+ (req->answers == update->preqs) &&
+ (req->auths == update->updates) &&
+ (req->additionals == update->additionals));
+#endif
+
+ return req;
+}
+
+struct dns_update_request *dns_request2update(struct dns_request *request)
+{
+ /*
+ * For portability concerns see dns_update2request;
+ */
+ return (struct dns_update_request *)(void *)request;
+}
+
+DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx,
+ struct dns_update_request *update,
+ struct dns_buffer **pbuf)
+{
+ return dns_marshall_request(mem_ctx, dns_update2request(update), pbuf);
+}
+
+DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx,
+ struct dns_buffer *buf,
+ struct dns_update_request **pupreq)
+{
+ /*
+ * See comments above about portability. If the above works, this will
+ * as well.
+ */
+
+ return dns_unmarshall_request(mem_ctx, buf,
+ (struct dns_request **)(void *)pupreq);
+}
+
+uint16 dns_response_code(uint16 flags)
+{
+ return flags & 0xF;
+}
diff --git a/source/libaddns/dnsrecord.c b/source/libaddns/dnsrecord.c
new file mode 100644
index 00000000000..37a5886af70
--- /dev/null
+++ b/source/libaddns/dnsrecord.c
@@ -0,0 +1,413 @@
+/*
+ Linux DNS client library implementation
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "dns.h"
+
+DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
+ uint16 q_type, uint16 q_class,
+ struct dns_request **preq )
+{
+ struct dns_request *req;
+ struct dns_question *q;
+ DNS_ERROR err;
+
+ if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
+ !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
+ !(req->questions[0] = talloc(req->questions,
+ struct dns_question))) {
+ TALLOC_FREE(req);
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ req->id = random();
+
+ req->num_questions = 1;
+ q = req->questions[0];
+
+ err = dns_domain_name_from_string(q, name, &q->name);
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(req);
+ return err;
+ }
+
+ q->q_type = q_type;
+ q->q_class = q_class;
+
+ *preq = req;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
+ struct dns_update_request **preq )
+{
+ struct dns_update_request *req;
+ struct dns_zone *z;
+ DNS_ERROR err;
+
+ if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
+ !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
+ !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
+ TALLOC_FREE(req);
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ req->id = random();
+ req->flags = 0x2800; /* Dynamic update */
+
+ req->num_zones = 1;
+ z = req->zones[0];
+
+ err = dns_domain_name_from_string(z, name, &z->name);
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(req);
+ return err;
+ }
+
+ z->z_type = QTYPE_SOA;
+ z->z_class = DNS_CLASS_IN;
+
+ *preq = req;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
+ uint16 type, uint16 r_class, uint32 ttl,
+ uint16 data_length, uint8 *data,
+ struct dns_rrec **prec)
+{
+ struct dns_rrec *rec;
+ DNS_ERROR err;
+
+ if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_domain_name_from_string(rec, name, &rec->name);
+ if (!(ERR_DNS_IS_OK(err))) {
+ TALLOC_FREE(rec);
+ return err;
+ }
+
+ rec->type = type;
+ rec->r_class = r_class;
+ rec->ttl = ttl;
+ rec->data_length = data_length;
+ rec->data = talloc_move(rec, &data);
+
+ *prec = rec;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
+ uint32 ttl, struct in_addr ip,
+ struct dns_rrec **prec)
+{
+ uint8 *data;
+ DNS_ERROR err;
+
+ if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
+ sizeof(ip.s_addr)))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
+ sizeof(ip.s_addr), data, prec);
+
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(data);
+ }
+
+ return err;
+}
+
+DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
+ const char *name,
+ const struct in_addr *ip,
+ struct dns_rrec **prec)
+{
+ if (ip != NULL) {
+ return dns_create_a_record(mem_ctx, name, 0, *ip, prec);
+ }
+
+ return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
+ NULL, prec);
+}
+
+DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
+ const char *name, uint32 type,
+ struct dns_rrec **prec)
+{
+ return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
+ 0, NULL, prec);
+}
+
+DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
+ uint16 type, uint16 r_class,
+ struct dns_rrec **prec)
+{
+ return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
+}
+
+DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
+ const char *algorithm_name, time_t inception,
+ time_t expiration, uint16 mode, uint16 error,
+ uint16 key_length, const uint8 *key,
+ struct dns_rrec **prec)
+{
+ struct dns_buffer *buf;
+ struct dns_domain_name *algorithm;
+ DNS_ERROR err;
+
+ if (!(buf = dns_create_buffer(mem_ctx))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ dns_marshall_domain_name(buf, algorithm);
+ dns_marshall_uint32(buf, inception);
+ dns_marshall_uint32(buf, expiration);
+ dns_marshall_uint16(buf, mode);
+ dns_marshall_uint16(buf, error);
+ dns_marshall_uint16(buf, key_length);
+ dns_marshall_buffer(buf, key, key_length);
+ dns_marshall_uint16(buf, 0); /* Other Size */
+
+ if (!ERR_DNS_IS_OK(buf->error)) {
+ err = buf->error;
+ goto error;
+ }
+
+ err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
+ buf->offset, buf->data, prec);
+
+ error:
+ TALLOC_FREE(buf);
+ return err;
+}
+
+DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
+ struct dns_tkey_record **ptkey)
+{
+ struct dns_tkey_record *tkey;
+ struct dns_buffer buf;
+ uint32 tmp_inception, tmp_expiration;
+
+ if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ buf.data = rec->data;
+ buf.size = rec->data_length;
+ buf.offset = 0;
+ buf.error = ERROR_DNS_SUCCESS;
+
+ dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
+ dns_unmarshall_uint32(&buf, &tmp_inception);
+ dns_unmarshall_uint32(&buf, &tmp_expiration);
+ dns_unmarshall_uint16(&buf, &tkey->mode);
+ dns_unmarshall_uint16(&buf, &tkey->error);
+ dns_unmarshall_uint16(&buf, &tkey->key_length);
+
+ if (!ERR_DNS_IS_OK(buf.error)) goto error;
+
+ if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
+ buf.error = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
+ if (!ERR_DNS_IS_OK(buf.error)) goto error;
+
+ tkey->inception = (time_t)tmp_inception;
+ tkey->expiration = (time_t)tmp_expiration;
+
+ *ptkey = tkey;
+ return ERROR_DNS_SUCCESS;
+
+ error:
+ TALLOC_FREE(tkey);
+ return buf.error;
+}
+
+DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
+ const char *algorithm_name,
+ time_t time_signed, uint16 fudge,
+ uint16 mac_length, const uint8 *mac,
+ uint16 original_id, uint16 error,
+ struct dns_rrec **prec)
+{
+ struct dns_buffer *buf;
+ struct dns_domain_name *algorithm;
+ DNS_ERROR err;
+
+ if (!(buf = dns_create_buffer(mem_ctx))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ dns_marshall_domain_name(buf, algorithm);
+ dns_marshall_uint16(buf, 0); /* time prefix */
+ dns_marshall_uint32(buf, time_signed);
+ dns_marshall_uint16(buf, fudge);
+ dns_marshall_uint16(buf, mac_length);
+ dns_marshall_buffer(buf, mac, mac_length);
+ dns_marshall_uint16(buf, original_id);
+ dns_marshall_uint16(buf, error);
+ dns_marshall_uint16(buf, 0); /* Other Size */
+
+ if (!ERR_DNS_IS_OK(buf->error)) {
+ err = buf->error;
+ goto error;
+ }
+
+ err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
+ buf->offset, buf->data, prec);
+
+ error:
+ TALLOC_FREE(buf);
+ return err;
+}
+
+DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
+ uint16 *num_records, struct dns_rrec ***records)
+{
+ struct dns_rrec **new_records;
+
+ if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
+ struct dns_rrec *,
+ (*num_records)+1))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ new_records[*num_records] = talloc_move(new_records, &rec);
+
+ *num_records += 1;
+ *records = new_records;
+ return ERROR_DNS_SUCCESS;
+}
+
+/*
+ * Create a request that probes a server whether the list of IP addresses
+ * provides meets our expectations
+ */
+
+DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
+ const char *host, int num_ips,
+ const struct in_addr *iplist,
+ struct dns_update_request **preq)
+{
+ struct dns_update_request *req;
+ struct dns_rrec *rec;
+ DNS_ERROR err;
+ uint16 i;
+
+ err = dns_create_update(mem_ctx, zone, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ for (i=0; i<num_ips; i++) {
+ err = dns_create_name_in_use_record(req, host,
+ &iplist[i], &rec);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+ }
+
+ *preq = req;
+ return ERROR_DNS_SUCCESS;
+
+ error:
+ TALLOC_FREE(req);
+ return err;
+}
+
+DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
+ const char *domainname,
+ const char *hostname,
+ const struct in_addr *ip_addrs,
+ size_t num_addrs,
+ struct dns_update_request **preq)
+{
+ struct dns_update_request *req;
+ struct dns_rrec *rec;
+ DNS_ERROR err;
+ size_t i;
+
+ err = dns_create_update(mem_ctx, domainname, &req);
+ if (!ERR_DNS_IS_OK(err)) return err;
+
+ /*
+ * The zone must be used at all
+ */
+
+ err = dns_create_rrec(req, domainname, QTYPE_ANY, DNS_CLASS_ANY,
+ 0, 0, NULL, &rec);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ /*
+ * Delete any existing A records
+ */
+
+ err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
+ &rec);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ /*
+ * .. and add our IPs
+ */
+
+ for ( i=0; i<num_addrs; i++ ) {
+ err = dns_create_a_record(req, hostname, 3600, ip_addrs[i], &rec);
+ if (!ERR_DNS_IS_OK(err))
+ goto error;
+
+ err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
+ if (!ERR_DNS_IS_OK(err))
+ goto error;
+ }
+
+ *preq = req;
+ return ERROR_DNS_SUCCESS;
+
+ error:
+ TALLOC_FREE(req);
+ return err;
+}
diff --git a/source/libaddns/dnssock.c b/source/libaddns/dnssock.c
new file mode 100644
index 00000000000..5dbedc4fd51
--- /dev/null
+++ b/source/libaddns/dnssock.c
@@ -0,0 +1,374 @@
+/*
+ Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "dns.h"
+#include <sys/time.h>
+#include <unistd.h>
+
+static int destroy_dns_connection(struct dns_connection *conn)
+{
+ return close(conn->s);
+}
+
+/********************************************************************
+********************************************************************/
+
+static DNS_ERROR dns_tcp_open( const char *nameserver,
+ TALLOC_CTX *mem_ctx,
+ struct dns_connection **result )
+{
+ uint32_t ulAddress;
+ struct hostent *pHost;
+ struct sockaddr_in s_in;
+ struct dns_connection *conn;
+ int res;
+
+ if (!(conn = talloc(mem_ctx, struct dns_connection))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
+ if ( (pHost = gethostbyname( nameserver )) == NULL ) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_INVALID_NAME_SERVER;
+ }
+ memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
+ }
+
+ conn->s = socket( PF_INET, SOCK_STREAM, 0 );
+ if (conn->s == -1) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_CONNECTION_FAILED;
+ }
+
+ talloc_set_destructor(conn, destroy_dns_connection);
+
+ s_in.sin_family = AF_INET;
+ s_in.sin_addr.s_addr = ulAddress;
+ s_in.sin_port = htons( DNS_TCP_PORT );
+
+ res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
+ if (res == -1) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_CONNECTION_FAILED;
+ }
+
+ conn->hType = DNS_TCP;
+
+ *result = conn;
+ return ERROR_DNS_SUCCESS;
+}
+
+/********************************************************************
+********************************************************************/
+
+static DNS_ERROR dns_udp_open( const char *nameserver,
+ TALLOC_CTX *mem_ctx,
+ struct dns_connection **result )
+{
+ unsigned long ulAddress;
+ struct hostent *pHost;
+ struct sockaddr_in RecvAddr;
+ struct dns_connection *conn;
+
+ if (!(conn = talloc(NULL, struct dns_connection))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
+ if ( (pHost = gethostbyname( nameserver )) == NULL ) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_INVALID_NAME_SERVER;
+ }
+ memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
+ }
+
+ /* Create a socket for sending data */
+
+ conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ if (conn->s == -1) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_CONNECTION_FAILED;
+ }
+
+ talloc_set_destructor(conn, destroy_dns_connection);
+
+ /* Set up the RecvAddr structure with the IP address of
+ the receiver (in this example case "123.456.789.1")
+ and the specified port number. */
+
+ RecvAddr.sin_family = AF_INET;
+ RecvAddr.sin_port = htons( DNS_UDP_PORT );
+ RecvAddr.sin_addr.s_addr = ulAddress;
+
+ conn->hType = DNS_UDP;
+ memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
+
+ *result = conn;
+ return ERROR_DNS_SUCCESS;
+}
+
+/********************************************************************
+********************************************************************/
+
+DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
+ TALLOC_CTX *mem_ctx,
+ struct dns_connection **conn )
+{
+ switch ( dwType ) {
+ case DNS_TCP:
+ return dns_tcp_open( nameserver, mem_ctx, conn );
+ case DNS_UDP:
+ return dns_udp_open( nameserver, mem_ctx, conn );
+ }
+
+ return ERROR_DNS_INVALID_PARAMETER;
+}
+
+static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
+{
+ size_t total = 0;
+
+ while (total < len) {
+
+ ssize_t ret = write(fd, data + total, len - total);
+
+ if (ret <= 0) {
+ /*
+ * EOF or error
+ */
+ return ERROR_DNS_SOCKET_ERROR;
+ }
+
+ total += ret;
+ }
+
+ return ERROR_DNS_SUCCESS;
+}
+
+static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
+ const struct dns_buffer *buf)
+{
+ uint16 len = htons(buf->offset);
+ DNS_ERROR err;
+
+ err = write_all(conn->s, (uint8 *)&len, sizeof(len));
+ if (!ERR_DNS_IS_OK(err)) return err;
+
+ return write_all(conn->s, buf->data, buf->offset);
+}
+
+static DNS_ERROR dns_send_udp(struct dns_connection *conn,
+ const struct dns_buffer *buf)
+{
+ ssize_t ret;
+
+ ret = sendto(conn->s, buf->data, buf->offset, 0,
+ (struct sockaddr *)&conn->RecvAddr,
+ sizeof(conn->RecvAddr));
+
+ if (ret != buf->offset) {
+ return ERROR_DNS_SOCKET_ERROR;
+ }
+
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
+{
+ if (conn->hType == DNS_TCP) {
+ return dns_send_tcp(conn, buf);
+ }
+
+ if (conn->hType == DNS_UDP) {
+ return dns_send_udp(conn, buf);
+ }
+
+ return ERROR_DNS_INVALID_PARAMETER;
+}
+
+static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
+{
+ size_t total = 0;
+ fd_set rfds;
+ struct timeval tv;
+
+ while (total < len) {
+ ssize_t ret;
+ int fd_ready;
+
+ FD_ZERO( &rfds );
+ FD_SET( fd, &rfds );
+
+ /* 10 second timeout */
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+
+ fd_ready = select( fd+1, &rfds, NULL, NULL, &tv );
+ if ( fd_ready == 0 ) {
+ /* read timeout */
+ return ERROR_DNS_SOCKET_ERROR;
+ }
+
+ ret = read(fd, data + total, len - total);
+ if (ret <= 0) {
+ /* EOF or error */
+ return ERROR_DNS_SOCKET_ERROR;
+ }
+
+ total += ret;
+ }
+
+ return ERROR_DNS_SUCCESS;
+}
+
+static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
+ struct dns_connection *conn,
+ struct dns_buffer **presult)
+{
+ struct dns_buffer *buf;
+ DNS_ERROR err;
+ uint16 len;
+
+ if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = read_all(conn->s, (uint8 *)&len, sizeof(len));
+ if (!ERR_DNS_IS_OK(err)) {
+ return err;
+ }
+
+ buf->size = ntohs(len);
+
+ if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
+ TALLOC_FREE(buf);
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = read_all(conn->s, buf->data, buf->size);
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(buf);
+ return err;
+ }
+
+ *presult = buf;
+ return ERROR_DNS_SUCCESS;
+}
+
+static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
+ struct dns_connection *conn,
+ struct dns_buffer **presult)
+{
+ struct dns_buffer *buf;
+ ssize_t received;
+
+ if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ /*
+ * UDP based DNS can only be 512 bytes
+ */
+
+ if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
+ TALLOC_FREE(buf);
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ received = recv(conn->s, (void *)buf->data, 512, 0);
+
+ if (received == -1) {
+ TALLOC_FREE(buf);
+ return ERROR_DNS_SOCKET_ERROR;
+ }
+
+ if (received > 512) {
+ TALLOC_FREE(buf);
+ return ERROR_DNS_BAD_RESPONSE;
+ }
+
+ buf->size = received;
+ buf->offset = 0;
+
+ *presult = buf;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
+ struct dns_buffer **presult)
+{
+ if (conn->hType == DNS_TCP) {
+ return dns_receive_tcp(mem_ctx, conn, presult);
+ }
+
+ if (conn->hType == DNS_UDP) {
+ return dns_receive_udp(mem_ctx, conn, presult);
+ }
+
+ return ERROR_DNS_INVALID_PARAMETER;
+}
+
+DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
+ const struct dns_request *req,
+ struct dns_request **resp)
+{
+ struct dns_buffer *buf = NULL;
+ DNS_ERROR err;
+
+ err = dns_marshall_request(conn, req, &buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_send(conn, buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+ TALLOC_FREE(buf);
+
+ err = dns_receive(mem_ctx, conn, &buf);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_unmarshall_request(mem_ctx, buf, resp);
+
+ error:
+ TALLOC_FREE(buf);
+ return err;
+}
+
+DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
+ struct dns_connection *conn,
+ struct dns_update_request *up_req,
+ struct dns_update_request **up_resp)
+{
+ struct dns_request *resp;
+ DNS_ERROR err;
+
+ err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
+ &resp);
+
+ if (!ERR_DNS_IS_OK(err)) return err;
+
+ *up_resp = dns_request2update(resp);
+ return ERROR_DNS_SUCCESS;
+}
diff --git a/source/libaddns/dnsutils.c b/source/libaddns/dnsutils.c
new file mode 100644
index 00000000000..5f0ab042195
--- /dev/null
+++ b/source/libaddns/dnsutils.c
@@ -0,0 +1,153 @@
+/*
+ Linux DNS client library implementation
+
+ Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
+ Copyright (C) 2006 Gerald Carter <jerry@samba.org>
+
+ ** NOTE! The following LGPL license applies to the libaddns
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "dns.h"
+#include <ctype.h>
+
+static DNS_ERROR LabelList( TALLOC_CTX *mem_ctx,
+ const char *name,
+ struct dns_domain_label **presult )
+{
+ struct dns_domain_label *result;
+ const char *dot;
+
+ for (dot = name; *dot != '\0'; dot += 1) {
+ char c = *dot;
+
+ if (c == '.')
+ break;
+
+ if (c == '-') continue;
+ if ((c >= 'a') && (c <= 'z')) continue;
+ if ((c >= 'A') && (c <= 'Z')) continue;
+ if ((c >= '0') && (c <= '9')) continue;
+
+ return ERROR_DNS_INVALID_NAME;
+ }
+
+ if ((dot - name) > 63) {
+ /*
+ * DNS labels can only be 63 chars long
+ */
+ return ERROR_DNS_INVALID_NAME;
+ }
+
+ if (!(result = TALLOC_ZERO_P(mem_ctx, struct dns_domain_label))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ if (*dot == '\0') {
+ /*
+ * No dot around, so this is the last component
+ */
+
+ if (!(result->label = talloc_strdup(result, name))) {
+ TALLOC_FREE(result);
+ return ERROR_DNS_NO_MEMORY;
+ }
+ result->len = strlen(result->label);
+ *presult = result;
+ return ERROR_DNS_SUCCESS;
+ }
+
+ if (dot[1] == '.') {
+ /*
+ * Two dots in a row, reject
+ */
+
+ TALLOC_FREE(result);
+ return ERROR_DNS_INVALID_NAME;
+ }
+
+ if (dot[1] != '\0') {
+ /*
+ * Something follows, get the rest
+ */
+
+ DNS_ERROR err = LabelList(result, dot+1, &result->next);
+
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(result);
+ return err;
+ }
+ }
+
+ result->len = (dot - name);
+
+ if (!(result->label = talloc_strndup(result, name, result->len))) {
+ TALLOC_FREE(result);
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ *presult = result;
+ return ERROR_DNS_SUCCESS;
+}
+
+DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx,
+ const char *pszDomainName,
+ struct dns_domain_name **presult )
+{
+ struct dns_domain_name *result;
+ DNS_ERROR err;
+
+ if (!(result = talloc(mem_ctx, struct dns_domain_name))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = LabelList( result, pszDomainName, &result->pLabelList );
+ if (!ERR_DNS_IS_OK(err)) {
+ TALLOC_FREE(result);
+ return err;
+ }
+
+ *presult = result;
+ return ERROR_DNS_SUCCESS;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+char *dns_generate_keyname( TALLOC_CTX *mem_ctx )
+{
+ char *result = NULL;
+#if defined(WITH_DNS_UPDATES)
+
+ uuid_t uuid;
+
+ /*
+ * uuid_unparse gives 36 bytes plus '\0'
+ */
+ if (!(result = TALLOC_ARRAY(mem_ctx, char, 37))) {
+ return NULL;
+ }
+
+ uuid_generate( uuid );
+ uuid_unparse( uuid, result );
+
+#endif
+
+ return result;
+}
diff --git a/source/libads/ads_status.c b/source/libads/ads_status.c
index 536ef766e37..017d38c6001 100644
--- a/source/libads/ads_status.c
+++ b/source/libads/ads_status.c
@@ -69,25 +69,29 @@ ADS_STATUS ads_build_nt_error(enum ads_error_type etype,
*/
NTSTATUS ads_ntstatus(ADS_STATUS status)
{
- if (status.error_type == ENUM_ADS_ERROR_NT){
+ switch (status.error_type) {
+ case ENUM_ADS_ERROR_NT:
return status.err.nt_status;
- }
+ case ENUM_ADS_ERROR_SYSTEM:
+ return map_nt_error_from_unix(status.err.rc);
#ifdef HAVE_LDAP
- if ((status.error_type == ENUM_ADS_ERROR_LDAP)
- && (status.err.rc == LDAP_NO_MEMORY)) {
- return NT_STATUS_NO_MEMORY;
- }
+ case ENUM_ADS_ERROR_LDAP:
+ if (status.err.rc == LDAP_SUCCESS) {
+ return NT_STATUS_OK;
+ }
+ return NT_STATUS_LDAP(status.err.rc);
#endif
#ifdef HAVE_KRB5
- if (status.error_type == ENUM_ADS_ERROR_KRB5) {
- if (status.err.rc == KRB5KDC_ERR_PREAUTH_FAILED) {
- return NT_STATUS_LOGON_FAILURE;
- } else if (status.err.rc == KRB5_KDC_UNREACH) {
- return NT_STATUS_NO_LOGON_SERVERS;
- }
- }
+ case ENUM_ADS_ERROR_KRB5:
+ return krb5_to_nt_status(status.err.rc);
#endif
- if (ADS_ERR_OK(status)) return NT_STATUS_OK;
+ default:
+ break;
+ }
+
+ if (ADS_ERR_OK(status)) {
+ return NT_STATUS_OK;
+ }
return NT_STATUS_UNSUCCESSFUL;
}
diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c
index 7a03a2a80f6..05f066c9fa5 100644
--- a/source/libads/ads_struct.c
+++ b/source/libads/ads_struct.c
@@ -42,7 +42,7 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
- ret = SMB_MALLOC(len);
+ ret = (char *)SMB_MALLOC(len);
if (!ret)
return NULL;
@@ -75,6 +75,28 @@ char *ads_build_dn(const char *realm)
return ads_build_path(realm, ".", "dc=", 0);
}
+/* return a DNS name in the for aa.bb.cc from the DN
+ "dc=AA,dc=BB,dc=CC". caller must free
+*/
+char *ads_build_domain(const char *dn)
+{
+ char *dnsdomain = NULL;
+
+ /* result should always be shorter than the DN */
+
+ if ( (dnsdomain = SMB_STRDUP( dn )) == NULL ) {
+ DEBUG(0,("ads_build_domain: malloc() failed!\n"));
+ return NULL;
+ }
+
+ strlower_m( dnsdomain );
+ all_string_sub( dnsdomain, "dc=", "", 0);
+ all_string_sub( dnsdomain, ",", ".", 0 );
+
+ return dnsdomain;
+}
+
+
#ifndef LDAP_PORT
#define LDAP_PORT 389
@@ -136,12 +158,8 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->config.realm);
SAFE_FREE((*ads)->config.bind_path);
SAFE_FREE((*ads)->config.ldap_server_name);
-
- SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
- SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
- SAFE_FREE((*ads)->schema.posix_shell_attr);
- SAFE_FREE((*ads)->schema.posix_homedir_attr);
- SAFE_FREE((*ads)->schema.posix_gecos_attr);
+ SAFE_FREE((*ads)->config.server_site_name);
+ SAFE_FREE((*ads)->config.client_site_name);
ZERO_STRUCTP(*ads);
diff --git a/source/libads/ads_utils.c b/source/libads/ads_utils.c
index 0cbf235989e..5b450e02dda 100644
--- a/source/libads/ads_utils.c
+++ b/source/libads/ads_utils.c
@@ -135,7 +135,7 @@ uint32 ads_gtype2atype(uint32 gtype)
}
/* turn a sAMAccountType into a SID_NAME_USE */
-enum SID_NAME_USE ads_atype_map(uint32 atype)
+enum lsa_SidType ads_atype_map(uint32 atype)
{
switch (atype & 0xF0000000) {
case ATYPE_GLOBAL_GROUP:
diff --git a/source/libads/authdata.c b/source/libads/authdata.c
index c3c160dafba..71294941a60 100644
--- a/source/libads/authdata.c
+++ b/source/libads/authdata.c
@@ -878,9 +878,9 @@ static void dump_pac_logon_info(PAC_LOGON_INFO *logon_info) {
DEBUG(2,("decode_pac_data: Logon time mismatch between ticket and PAC!\n"));
DEBUGADD(2, ("decode_pac_data: PAC: %s\n",
- http_timestring(nt_time_to_unix(&logon_name->logon_time))));
+ http_timestring(nt_time_to_unix(logon_name->logon_time))));
DEBUGADD(2, ("decode_pac_data: Ticket: %s\n",
- http_timestring(nt_time_to_unix(&tgs_authtime_nttime))));
+ http_timestring(nt_time_to_unix(tgs_authtime_nttime))));
nt_status = NT_STATUS_ACCESS_DENIED;
goto out;
diff --git a/source/libads/cldap.c b/source/libads/cldap.c
index 174064464f9..72018c620d8 100644
--- a/source/libads/cldap.c
+++ b/source/libads/cldap.c
@@ -190,6 +190,8 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
DATA_BLOB blob;
DATA_BLOB os1, os2, os3;
int i1;
+ /* half the time of a regular ldap timeout, not less than 3 seconds. */
+ unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
char *p;
blob = data_blob(NULL, 8192);
@@ -202,7 +204,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
/* Setup timeout */
gotalarm = 0;
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
- alarm(lp_ldap_timeout());
+ alarm(al_secs);
/* End setup timeout. */
ret = read(sock, blob.data, blob.length);
@@ -262,8 +264,8 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
*reply->user_name = 0;
}
- p += pull_netlogon_string(reply->site_name, p, (const char *)os3.data);
- p += pull_netlogon_string(reply->site_name_2, p, (const char *)os3.data);
+ p += pull_netlogon_string(reply->server_site_name, p, (const char *)os3.data);
+ p += pull_netlogon_string(reply->client_site_name, p, (const char *)os3.data);
reply->version = IVAL(p, 0);
reply->lmnt_token = SVAL(p, 4);
@@ -309,5 +311,3 @@ BOOL ads_cldap_netlogon(const char *server, const char *realm, struct cldap_net
return True;
}
-
-
diff --git a/source/libads/disp_sec.c b/source/libads/disp_sec.c
index c9de447e698..f0f1765b237 100644
--- a/source/libads/disp_sec.c
+++ b/source/libads/disp_sec.c
@@ -90,13 +90,13 @@ static void ads_disp_ace(SEC_ACE *sec_ace)
sec_ace->type,
sec_ace->flags,
sec_ace->size,
- sec_ace->info.mask);
+ sec_ace->access_mask);
} else {
printf("------- ACE (type: 0x%02x, flags: 0x%02x, size: 0x%02x, mask: 0x%x, object flags: 0x%x)\n",
sec_ace->type,
sec_ace->flags,
sec_ace->size,
- sec_ace->info.mask,
+ sec_ace->access_mask,
sec_ace->obj_flags);
}
@@ -117,7 +117,7 @@ static void ads_disp_ace(SEC_ACE *sec_ace)
printf("access SID: %s\naccess type: %s\n",
sid_string_static(&sec_ace->trustee), access_type);
- ads_disp_perms(sec_ace->info.mask);
+ ads_disp_perms(sec_ace->access_mask);
}
/* display ACL */
@@ -143,15 +143,15 @@ void ads_disp_sd(SEC_DESC *sd)
sd->revision,
sd->type);
printf("owner SID: %s\n", sid_string_static(sd->owner_sid));
- printf("group SID: %s\n", sid_string_static(sd->grp_sid));
+ printf("group SID: %s\n", sid_string_static(sd->group_sid));
ads_disp_acl(sd->sacl, "system");
for (i = 0; i < sd->sacl->num_aces; i ++)
- ads_disp_ace(&sd->sacl->ace[i]);
+ ads_disp_ace(&sd->sacl->aces[i]);
ads_disp_acl(sd->dacl, "user");
for (i = 0; i < sd->dacl->num_aces; i ++)
- ads_disp_ace(&sd->dacl->ace[i]);
+ ads_disp_ace(&sd->dacl->aces[i]);
printf("-------------- End Of Security Descriptor\n");
}
diff --git a/source/libads/dns.c b/source/libads/dns.c
index 23c76213cf4..008266ea0b0 100644
--- a/source/libads/dns.c
+++ b/source/libads/dns.c
@@ -46,6 +46,9 @@
# define T_A ns_t_a
#endif
# define T_SRV ns_t_srv
+#if !defined(T_NS) /* AIX 5.3 already defines T_NS */
+# define T_NS ns_t_ns
+#endif
#else
# ifdef HFIXEDSZ
# define NS_HFIXEDSZ HFIXEDSZ
@@ -197,6 +200,46 @@ static BOOL ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
return True;
}
+/*********************************************************************
+*********************************************************************/
+
+static BOOL ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+ uint8 **ptr, struct dns_rr_ns *nsrec )
+{
+ struct dns_rr rr;
+ uint8 *p;
+ pstring nsname;
+ int namelen;
+
+ if ( !start || !end || !nsrec || !*ptr)
+ return -1;
+
+ /* Parse the RR entry. Coming out of the this, ptr is at the beginning
+ of the next record */
+
+ if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) {
+ DEBUG(1,("ads_dns_parse_rr_ns: Failed to parse RR record\n"));
+ return False;
+ }
+
+ if ( rr.type != T_NS ) {
+ DEBUG(1,("ads_dns_parse_rr_ns: Bad answer type (%d)\n", rr.type));
+ return False;
+ }
+
+ p = rr.rdata;
+
+ /* ame server hostname */
+
+ namelen = dn_expand( start, end, p, nsname, sizeof(nsname) );
+ if ( namelen < 0 ) {
+ DEBUG(1,("ads_dns_parse_rr_ns: Failed to uncompress name!\n"));
+ return False;
+ }
+ nsrec->hostname = talloc_strdup( ctx, nsname );
+
+ return True;
+}
/*********************************************************************
Sort SRV record list based on weight and priority. See RFC 2782.
@@ -224,27 +267,16 @@ static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b )
}
/*********************************************************************
- Simple wrapper for a DNS SRV query
+ Simple wrapper for a DNS query
*********************************************************************/
-NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_srv **dclist, int *numdcs )
+static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type,
+ uint8 **buf, int *resp_length )
{
uint8 *buffer = NULL;
size_t buf_len;
- int resp_len = NS_PACKETSZ;
- struct dns_rr_srv *dcs = NULL;
- int query_count, answer_count, auth_count, additional_count;
- uint8 *p = buffer;
- int rrnum;
- int idx = 0;
-
- if ( !ctx || !name || !dclist ) {
- return NT_STATUS_INVALID_PARAMETER;
- }
+ int resp_len = NS_PACKETSZ;
- /* Send the request. May have to loop several times in case
- of large replies */
-
do {
if ( buffer )
TALLOC_FREE( buffer );
@@ -256,13 +288,53 @@ NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_sr
return NT_STATUS_NO_MEMORY;
}
- if ( (resp_len = res_query(name, C_IN, T_SRV, buffer, buf_len)) < 0 ) {
- DEBUG(1,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
+ if ( (resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) < 0 ) {
+ DEBUG(3,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
TALLOC_FREE( buffer );
+ if (errno == ETIMEDOUT) {
+ return NT_STATUS_IO_TIMEOUT;
+ }
+ if (errno == ECONNREFUSED) {
+ return NT_STATUS_CONNECTION_REFUSED;
+ }
return NT_STATUS_UNSUCCESSFUL;
}
} while ( buf_len < resp_len && resp_len < MAX_DNS_PACKET_SIZE );
+
+ *buf = buffer;
+ *resp_length = resp_len;
+
+ return NT_STATUS_OK;
+}
+
+/*********************************************************************
+ Simple wrapper for a DNS SRV query
+*********************************************************************/
+static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_srv **dclist, int *numdcs )
+{
+ uint8 *buffer = NULL;
+ int resp_len = 0;
+ struct dns_rr_srv *dcs = NULL;
+ int query_count, answer_count, auth_count, additional_count;
+ uint8 *p = buffer;
+ int rrnum;
+ int idx = 0;
+ NTSTATUS status;
+
+ if ( !ctx || !name || !dclist ) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Send the request. May have to loop several times in case
+ of large replies */
+
+ status = dns_send_req( ctx, name, T_SRV, &buffer, &resp_len );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(3,("ads_dns_lookup_srv: Failed to send DNS query (%s)\n",
+ nt_errstr(status)));
+ return status;
+ }
p = buffer;
/* For some insane reason, the ns_initparse() et. al. routines are only
@@ -383,15 +455,326 @@ NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_sr
return NT_STATUS_OK;
}
+/*********************************************************************
+ Simple wrapper for a DNS NS query
+*********************************************************************/
+
+NTSTATUS ads_dns_lookup_ns( TALLOC_CTX *ctx, const char *dnsdomain, struct dns_rr_ns **nslist, int *numns )
+{
+ uint8 *buffer = NULL;
+ int resp_len = 0;
+ struct dns_rr_ns *nsarray = NULL;
+ int query_count, answer_count, auth_count, additional_count;
+ uint8 *p;
+ int rrnum;
+ int idx = 0;
+ NTSTATUS status;
+
+ if ( !ctx || !dnsdomain || !nslist ) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Send the request. May have to loop several times in case
+ of large replies */
+
+ status = dns_send_req( ctx, dnsdomain, T_NS, &buffer, &resp_len );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(3,("ads_dns_lookup_ns: Failed to send DNS query (%s)\n",
+ nt_errstr(status)));
+ return status;
+ }
+ p = buffer;
+
+ /* For some insane reason, the ns_initparse() et. al. routines are only
+ available in libresolv.a, and not the shared lib. Who knows why....
+ So we have to parse the DNS reply ourselves */
+
+ /* Pull the answer RR's count from the header. Use the NMB ordering macros */
+
+ query_count = RSVAL( p, 4 );
+ answer_count = RSVAL( p, 6 );
+ auth_count = RSVAL( p, 8 );
+ additional_count = RSVAL( p, 10 );
+
+ DEBUG(4,("ads_dns_lookup_ns: %d records returned in the answer section.\n",
+ answer_count));
+
+ if ( (nsarray = TALLOC_ARRAY(ctx, struct dns_rr_ns, answer_count)) == NULL ) {
+ DEBUG(0,("ads_dns_lookup_ns: talloc() failure for %d char*'s\n",
+ answer_count));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* now skip the header */
+
+ p += NS_HFIXEDSZ;
+
+ /* parse the query section */
+
+ for ( rrnum=0; rrnum<query_count; rrnum++ ) {
+ struct dns_query q;
+
+ if ( !ads_dns_parse_query( ctx, buffer, buffer+resp_len, &p, &q ) ) {
+ DEBUG(1,("ads_dns_lookup_ns: Failed to parse query record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* now we are at the answer section */
+
+ for ( rrnum=0; rrnum<answer_count; rrnum++ ) {
+ if ( !ads_dns_parse_rr_ns( ctx, buffer, buffer+resp_len, &p, &nsarray[rrnum] ) ) {
+ DEBUG(1,("ads_dns_lookup_ns: Failed to parse answer record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ idx = rrnum;
+
+ /* Parse the authority section */
+ /* just skip these for now */
+
+ for ( rrnum=0; rrnum<auth_count; rrnum++ ) {
+ struct dns_rr rr;
+
+ if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
+ DEBUG(1,("ads_dns_lookup_ns: Failed to parse authority record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* Parse the additional records section */
+
+ for ( rrnum=0; rrnum<additional_count; rrnum++ ) {
+ struct dns_rr rr;
+ int i;
+
+ if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
+ DEBUG(1,("ads_dns_lookup_ns: Failed to parse additional records section!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* only interested in A records as a shortcut for having to come
+ back later and lookup the name */
+
+ if ( (rr.type != T_A) || (rr.rdatalen != 4) )
+ continue;
+
+ for ( i=0; i<idx; i++ ) {
+ if ( strcmp( rr.hostname, nsarray[i].hostname ) == 0 ) {
+ uint8 *buf = (uint8*)&nsarray[i].ip.s_addr;
+ memcpy( buf, rr.rdata, 4 );
+ }
+ }
+ }
+
+ *nslist = nsarray;
+ *numns = idx;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Store and fetch the AD client sitename.
+****************************************************************************/
+
+#define SITENAME_KEY "AD_SITENAME/DOMAIN/%s"
+
+static char *sitename_key(const char *realm)
+{
+ char *keystr;
+
+ if (asprintf(&keystr, SITENAME_KEY, strupper_static(realm)) == -1) {
+ return NULL;
+ }
+
+ return keystr;
+}
+
+
+/****************************************************************************
+ Store the AD client sitename.
+ We store indefinately as every new CLDAP query will re-write this.
+ If the sitename is "Default-First-Site-Name" we don't store it
+ as this isn't a valid DNS name.
+****************************************************************************/
+
+BOOL sitename_store(const char *realm, const char *sitename)
+{
+ time_t expire;
+ BOOL ret = False;
+ char *key;
+
+ if (!gencache_init()) {
+ return False;
+ }
+
+ if (!realm || (strlen(realm) == 0)) {
+ DEBUG(0,("no realm\n"));
+ return False;
+ }
+
+ key = sitename_key(realm);
+
+ if (!sitename || (sitename && !*sitename)) {
+ DEBUG(5,("sitename_store: deleting empty sitename!\n"));
+ ret = gencache_del(key);
+ SAFE_FREE(key);
+ return ret;
+ }
+
+ expire = get_time_t_max(); /* Store indefinately. */
+
+ DEBUG(10,("sitename_store: realm = [%s], sitename = [%s], expire = [%u]\n",
+ realm, sitename, (unsigned int)expire ));
+
+ ret = gencache_set( key, sitename, expire );
+ SAFE_FREE(key);
+ return ret;
+}
+
+/****************************************************************************
+ Fetch the AD client sitename.
+ Caller must free.
+****************************************************************************/
+
+char *sitename_fetch(const char *realm)
+{
+ char *sitename = NULL;
+ time_t timeout;
+ BOOL ret = False;
+ const char *query_realm;
+ char *key;
+
+ if (!gencache_init()) {
+ return False;
+ }
+
+ if (!realm || (strlen(realm) == 0)) {
+ query_realm = lp_realm();
+ } else {
+ query_realm = realm;
+ }
+
+ key = sitename_key(query_realm);
+
+ ret = gencache_get( key, &sitename, &timeout );
+ SAFE_FREE(key);
+ if ( !ret ) {
+ DEBUG(5,("sitename_fetch: No stored sitename for %s\n",
+ query_realm));
+ } else {
+ DEBUG(5,("sitename_fetch: Returning sitename for %s: \"%s\"\n",
+ query_realm, sitename ));
+ }
+ return sitename;
+}
+
+/****************************************************************************
+ Did the sitename change ?
+****************************************************************************/
+
+BOOL stored_sitename_changed(const char *realm, const char *sitename)
+{
+ BOOL ret = False;
+
+ char *new_sitename;
+
+ if (!realm || (strlen(realm) == 0)) {
+ DEBUG(0,("no realm\n"));
+ return False;
+ }
+
+ new_sitename = sitename_fetch(realm);
+
+ if (sitename && new_sitename && !strequal(sitename, new_sitename)) {
+ ret = True;
+ } else if ((sitename && !new_sitename) ||
+ (!sitename && new_sitename)) {
+ ret = True;
+ }
+ SAFE_FREE(new_sitename);
+ return ret;
+}
+
/********************************************************************
+ Query with optional sitename.
********************************************************************/
-NTSTATUS ads_dns_query_dcs( TALLOC_CTX *ctx, const char *domain, struct dns_rr_srv **dclist, int *numdcs )
+NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
+ const char *servicename,
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
{
- pstring name;
+ char *name;
+ if (sitename) {
+ name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
+ servicename, sitename, realm );
+ } else {
+ name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
+ servicename, realm );
+ }
+ if (!name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return ads_dns_lookup_srv( ctx, name, dclist, numdcs );
+}
- snprintf( name, sizeof(name), "_ldap._tcp.dc._msdcs.%s", domain );
+/********************************************************************
+ Query for AD DC's.
+********************************************************************/
- return ads_dns_lookup_srv( ctx, name, dclist, numdcs );
+NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
+{
+ NTSTATUS status;
+
+ status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
+ dclist, numdcs);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
+ return status;
+ }
+
+ if (sitename && !NT_STATUS_IS_OK(status)) {
+ /* Sitename DNS query may have failed. Try without. */
+ status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
+ dclist, numdcs);
+ }
+ return status;
}
+/********************************************************************
+ Query for AD KDC's.
+ Even if our underlying kerberos libraries are UDP only, this
+ is pretty safe as it's unlikely that a KDC supports TCP and not UDP.
+********************************************************************/
+
+NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx,
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
+{
+ NTSTATUS status;
+
+ status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
+ dclist, numdcs);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
+ return status;
+ }
+
+ if (sitename && !NT_STATUS_IS_OK(status)) {
+ /* Sitename DNS query may have failed. Try without. */
+ status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
+ dclist, numdcs);
+ }
+ return status;
+}
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index af4ba868313..8e8297b07e5 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -45,7 +45,8 @@ kerb_prompter(krb5_context ctx, void *data,
memset(prompts[0].reply->data, '\0', prompts[0].reply->length);
if (prompts[0].reply->length > 0) {
if (data) {
- strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+ strncpy(prompts[0].reply->data, (const char *)data,
+ prompts[0].reply->length-1);
prompts[0].reply->length = strlen(prompts[0].reply->data);
} else {
prompts[0].reply->length = 0;
@@ -74,7 +75,7 @@ int kerberos_kinit_password_ext(const char *principal,
krb5_ccache cc = NULL;
krb5_principal me;
krb5_creds my_creds;
- krb5_get_init_creds_opt opt;
+ krb5_get_init_creds_opt *opt = NULL;
smb_krb5_addresses *addr = NULL;
initialize_krb5_error_table();
@@ -85,8 +86,9 @@ int kerberos_kinit_password_ext(const char *principal,
krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
}
- DEBUG(10,("kerberos_kinit_password: using %s as ccache\n",
- cache_name ? cache_name: krb5_cc_default_name(ctx)));
+ DEBUG(10,("kerberos_kinit_password: using [%s] as ccache and config [%s]\n",
+ cache_name ? cache_name: krb5_cc_default_name(ctx),
+ getenv("KRB5_CONFIG")));
if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) {
krb5_free_context(ctx);
@@ -94,47 +96,64 @@ int kerberos_kinit_password_ext(const char *principal,
}
if ((code = smb_krb5_parse_name(ctx, principal, &me))) {
+ krb5_cc_close(ctx, cc);
krb5_free_context(ctx);
return code;
}
- krb5_get_init_creds_opt_init(&opt);
- krb5_get_init_creds_opt_set_renew_life(&opt, renewable_time);
- krb5_get_init_creds_opt_set_forwardable(&opt, 1);
-
- if (request_pac) {
+ code = krb5_get_init_creds_opt_alloc(ctx, &opt);
+ if (code) {
+ krb5_cc_close(ctx, cc);
+ krb5_free_context(ctx);
+ return code;
+ }
+
+ krb5_get_init_creds_opt_set_renew_life(opt, renewable_time);
+ krb5_get_init_creds_opt_set_forwardable(opt, True);
+#if 0
+ /* insane testing */
+ krb5_get_init_creds_opt_set_tkt_life(opt, 60);
+#endif
+
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
- code = krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+ if (request_pac) {
+ code = krb5_get_init_creds_opt_set_pac_request(ctx, opt, (krb5_boolean)request_pac);
if (code) {
+ krb5_cc_close(ctx, cc);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
}
-#endif
}
-
+#endif
if (add_netbios_addr) {
code = smb_krb5_gen_netbios_krb5_address(&addr);
if (code) {
+ krb5_cc_close(ctx, cc);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
}
- krb5_get_init_creds_opt_set_address_list(&opt, addr->addrs);
+ krb5_get_init_creds_opt_set_address_list(opt, addr->addrs);
}
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
- kerb_prompter, NULL, 0, NULL, &opt)))
+ kerb_prompter, NULL, 0, NULL, opt)))
{
+ krb5_get_init_creds_opt_free(opt);
smb_krb5_free_addresses(ctx, addr);
+ krb5_cc_close(ctx, cc);
krb5_free_principal(ctx, me);
- krb5_free_context(ctx);
+ krb5_free_context(ctx);
return code;
}
-
+
+ krb5_get_init_creds_opt_free(opt);
+
if ((code = krb5_cc_initialize(ctx, cc, me))) {
smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
+ krb5_cc_close(ctx, cc);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
@@ -201,7 +220,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
}
ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
- &ads->auth.expire, NULL, NULL, False, False, ads->auth.renewable);
+ &ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
@@ -463,4 +482,260 @@ int kerberos_kinit_password(const char *principal,
0);
}
+/************************************************************************
+ Create a string list of available kdc's, possibly searching by sitename.
+ Does DNS queries.
+************************************************************************/
+
+static char *get_kdc_ip_string(char *mem_ctx, const char *realm, const char *sitename, struct in_addr primary_ip)
+{
+ struct ip_service *ip_srv_site;
+ struct ip_service *ip_srv_nonsite;
+ int count_site, count_nonsite, i;
+ char *kdc_str = talloc_asprintf(mem_ctx, "\tkdc = %s\n",
+ inet_ntoa(primary_ip));
+
+ if (kdc_str == NULL) {
+ return NULL;
+ }
+
+ /* Get the KDC's only in this site. */
+
+ if (sitename) {
+
+ get_kdc_list(realm, sitename, &ip_srv_site, &count_site);
+
+ for (i = 0; i < count_site; i++) {
+ if (ip_equal(ip_srv_site[i].ip, primary_ip)) {
+ continue;
+ }
+ /* Append to the string - inefficient but not done often. */
+ kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+ kdc_str, inet_ntoa(ip_srv_site[i].ip));
+ if (!kdc_str) {
+ SAFE_FREE(ip_srv_site);
+ return NULL;
+ }
+ }
+ }
+
+ /* Get all KDC's. */
+
+ get_kdc_list(realm, NULL, &ip_srv_nonsite, &count_nonsite);
+
+ for (i = 0; i < count_nonsite; i++) {
+ int j;
+
+ if (ip_equal(ip_srv_nonsite[i].ip, primary_ip)) {
+ continue;
+ }
+
+ /* Ensure this isn't an IP already seen (YUK! this is n*n....) */
+ for (j = 0; j < count_site; j++) {
+ if (ip_equal(ip_srv_nonsite[i].ip, ip_srv_site[j].ip)) {
+ break;
+ }
+ /* As the lists are sorted we can break early if nonsite > site. */
+ if (ip_service_compare(&ip_srv_nonsite[i], &ip_srv_site[j]) > 0) {
+ break;
+ }
+ }
+ if (j != i) {
+ continue;
+ }
+
+ /* Append to the string - inefficient but not done often. */
+ kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+ kdc_str, inet_ntoa(ip_srv_nonsite[i].ip));
+ if (!kdc_str) {
+ SAFE_FREE(ip_srv_site);
+ SAFE_FREE(ip_srv_nonsite);
+ return NULL;
+ }
+ }
+
+
+ SAFE_FREE(ip_srv_site);
+ SAFE_FREE(ip_srv_nonsite);
+
+ DEBUG(10,("get_kdc_ip_string: Returning %s\n",
+ kdc_str ));
+
+ return kdc_str;
+}
+
+/************************************************************************
+ Create a specific krb5.conf file in the private directory pointing
+ at a specific kdc for a realm. Keyed off domain name. Sets
+ KRB5_CONFIG environment variable to point to this file. Must be
+ run as root or will fail (which is a good thing :-).
+************************************************************************/
+
+BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *domain,
+ const char *sitename, struct in_addr ip)
+{
+ char *dname = talloc_asprintf(NULL, "%s/smb_krb5", lp_lockdir());
+ char *tmpname = NULL;
+ char *fname = NULL;
+ char *file_contents = NULL;
+ char *kdc_ip_string = NULL;
+ size_t flen = 0;
+ ssize_t ret;
+ int fd;
+ char *realm_upper = NULL;
+
+ if (!dname) {
+ return False;
+ }
+ if ((mkdir(dname, 0755)==-1) && (errno != EEXIST)) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: "
+ "failed to create directory %s. Error was %s\n",
+ dname, strerror(errno) ));
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ tmpname = talloc_asprintf(dname, "%s/smb_tmp_krb5.XXXXXX", lp_lockdir());
+ if (!tmpname) {
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ fname = talloc_asprintf(dname, "%s/krb5.conf.%s", dname, domain);
+ if (!fname) {
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ DEBUG(10,("create_local_private_krb5_conf_for_domain: fname = %s, realm = %s, domain = %s\n",
+ fname, realm, domain ));
+
+ realm_upper = talloc_strdup(fname, realm);
+ strupper_m(realm_upper);
+
+ kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, ip);
+ if (!kdc_ip_string) {
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ file_contents = talloc_asprintf(fname, "[libdefaults]\n\tdefault_realm = %s\n\n"
+ "[realms]\n\t%s = {\n"
+ "\t%s\t}\n",
+ realm_upper, realm_upper, kdc_ip_string);
+
+ if (!file_contents) {
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ flen = strlen(file_contents);
+
+ fd = smb_mkstemp(tmpname);
+ if (fd == -1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed,"
+ " for file %s. Errno %s\n",
+ tmpname, strerror(errno) ));
+ }
+
+ if (fchmod(fd, 0644)==-1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: fchmod failed for %s."
+ " Errno %s\n",
+ tmpname, strerror(errno) ));
+ unlink(tmpname);
+ close(fd);
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ ret = write(fd, file_contents, flen);
+ if (flen != ret) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: write failed,"
+ " returned %d (should be %u). Errno %s\n",
+ (int)ret, (unsigned int)flen, strerror(errno) ));
+ unlink(tmpname);
+ close(fd);
+ TALLOC_FREE(dname);
+ return False;
+ }
+ if (close(fd)==-1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: close failed."
+ " Errno %s\n", strerror(errno) ));
+ unlink(tmpname);
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ if (rename(tmpname, fname) == -1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: rename "
+ "of %s to %s failed. Errno %s\n",
+ tmpname, fname, strerror(errno) ));
+ unlink(tmpname);
+ TALLOC_FREE(dname);
+ return False;
+ }
+
+ DEBUG(5,("create_local_private_krb5_conf_for_domain: wrote "
+ "file %s with realm %s KDC = %s\n",
+ fname, realm_upper, inet_ntoa(ip) ));
+
+ /* Set the environment variable to this file. */
+ setenv("KRB5_CONFIG", fname, 1);
+
+#if defined(OVERWRITE_SYSTEM_KRB5_CONF)
+
+#define SYSTEM_KRB5_CONF_PATH "/etc/krb5.conf"
+ /* Insanity, sheer insanity..... */
+
+ if (strequal(realm, lp_realm())) {
+ pstring linkpath;
+ int lret;
+
+ lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath, sizeof(linkpath)-1);
+ linkpath[sizeof(pstring)-1] = '\0';
+
+ if (lret == 0 || strcmp(linkpath, fname) == 0) {
+ /* Symlink already exists. */
+ TALLOC_FREE(dname);
+ return True;
+ }
+
+ /* Try and replace with a symlink. */
+ if (symlink(fname, SYSTEM_KRB5_CONF_PATH) == -1) {
+ if (errno != EEXIST) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: symlink "
+ "of %s to %s failed. Errno %s\n",
+ fname, SYSTEM_KRB5_CONF_PATH, strerror(errno) ));
+ TALLOC_FREE(dname);
+ return True; /* Not a fatal error. */
+ }
+
+ pstrcpy(linkpath, SYSTEM_KRB5_CONF_PATH);
+ pstrcat(linkpath, ".saved");
+
+ /* Yes, this is a race conditon... too bad. */
+ if (rename(SYSTEM_KRB5_CONF_PATH, linkpath) == -1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: rename "
+ "of %s to %s failed. Errno %s\n",
+ SYSTEM_KRB5_CONF_PATH, linkpath,
+ strerror(errno) ));
+ TALLOC_FREE(dname);
+ return True; /* Not a fatal error. */
+ }
+
+ if (symlink(fname, "/etc/krb5.conf") == -1) {
+ DEBUG(0,("create_local_private_krb5_conf_for_domain: "
+ "forced symlink of %s to /etc/krb5.conf failed. Errno %s\n",
+ fname, strerror(errno) ));
+ TALLOC_FREE(dname);
+ return True; /* Not a fatal error. */
+ }
+ }
+ }
+#endif
+
+ TALLOC_FREE(dname);
+
+ return True;
+}
#endif
diff --git a/source/libads/kerberos_keytab.c b/source/libads/kerberos_keytab.c
index 80d11d434b4..ba1a9165674 100644
--- a/source/libads/kerberos_keytab.c
+++ b/source/libads/kerberos_keytab.c
@@ -408,12 +408,7 @@ int ads_keytab_flush(ADS_STRUCT *ads)
DEBUG(3,("ads_keytab_flush: Using default keytab: %s\n", (char *) &keytab_name));
ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
if (ret) {
- DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
- goto out;
- }
- ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
- if (ret) {
- DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
+ DEBUG(1,("ads_keytab_flush: krb5_kt_resolve failed (%s)\n", error_message(ret)));
goto out;
}
@@ -530,13 +525,18 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
}
/* now add the userPrincipalName and sAMAccountName entries */
-
+
if ( (sam_account_name = ads_get_samaccountname( ads, ctx, machine_name)) == NULL ) {
DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's name in AD!\n"));
TALLOC_FREE( ctx );
return -1;
}
+ /* upper case the sAMAccountName to make it easier for apps to
+ know what case to use in the keytab file */
+
+ strupper_m( sam_account_name );
+
if ( (ret = ads_keytab_add_entry(ads, sam_account_name )) != 0 ) {
DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding sAMAccountName (%s)\n",
sam_account_name));
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index 3aa0860809d..2c114b1240e 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -88,71 +88,69 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
goto out;
}
- if (ret != KRB5_KT_END && ret != ENOENT ) {
- while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
- ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
- if (ret) {
- DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
- error_message(ret)));
- goto out;
+ while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
+ ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
+ if (ret) {
+ DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
+ error_message(ret)));
+ goto out;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
+
+ if (!strequal(entry_princ_s, valid_princ_formats[i])) {
+ continue;
}
- for (i = 0; i < sizeof(valid_princ_formats) / sizeof(valid_princ_formats[0]); i++) {
- if (strequal(entry_princ_s, valid_princ_formats[i])) {
- number_matched_principals++;
- p_packet->length = ticket->length;
- p_packet->data = (krb5_pointer)ticket->data;
- *pp_tkt = NULL;
-
- ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
- kt_entry.principal, keytab,
- NULL, pp_tkt, keyblock);
-
- if (ret) {
- DEBUG(10,("ads_keytab_verify_ticket: "
- "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n",
- entry_princ_s, error_message(ret)));
-
- /* workaround for MIT:
- * as krb5_ktfile_get_entry will
- * explicitly close the
- * krb5_keytab as soon as
- * krb5_rd_req has sucessfully
- * decrypted the ticket but the
- * ticket is not valid yet (due
- * to clockskew) there is no
- * point in querying more
- * keytab entries - Guenther */
-
- if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
- ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
- break;
- }
- } else {
- DEBUG(3,("ads_keytab_verify_ticket: "
- "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n",
- entry_princ_s));
- auth_ok = True;
- break;
- }
+ number_matched_principals++;
+ p_packet->length = ticket->length;
+ p_packet->data = (char *)ticket->data;
+ *pp_tkt = NULL;
+
+ ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
+ kt_entry.principal, keytab,
+ NULL, pp_tkt, keyblock);
+
+ if (ret) {
+ DEBUG(10,("ads_keytab_verify_ticket: "
+ "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n",
+ entry_princ_s, error_message(ret)));
+
+ /* workaround for MIT:
+ * as krb5_ktfile_get_entry will explicitly
+ * close the krb5_keytab as soon as krb5_rd_req
+ * has sucessfully decrypted the ticket but the
+ * ticket is not valid yet (due to clockskew)
+ * there is no point in querying more keytab
+ * entries - Guenther */
+
+ if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
+ ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+ break;
}
+ } else {
+ DEBUG(3,("ads_keytab_verify_ticket: "
+ "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n",
+ entry_princ_s));
+ auth_ok = True;
+ break;
}
+ }
- /* Free the name we parsed. */
- SAFE_FREE(entry_princ_s);
+ /* Free the name we parsed. */
+ SAFE_FREE(entry_princ_s);
- /* Free the entry we just read. */
- smb_krb5_kt_free_entry(context, &kt_entry);
- ZERO_STRUCT(kt_entry);
- }
- krb5_kt_end_seq_get(context, keytab, &kt_cursor);
+ /* Free the entry we just read. */
+ smb_krb5_kt_free_entry(context, &kt_entry);
+ ZERO_STRUCT(kt_entry);
}
+ krb5_kt_end_seq_get(context, keytab, &kt_cursor);
ZERO_STRUCT(kt_cursor);
out:
- for (i = 0; i < sizeof(valid_princ_formats) / sizeof(valid_princ_formats[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
SAFE_FREE(valid_princ_formats[i]);
}
@@ -228,7 +226,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
p_packet->length = ticket->length;
- p_packet->data = (krb5_pointer)ticket->data;
+ p_packet->data = (char *)ticket->data;
/* We need to setup a auth context with each possible encoding type in turn. */
for (i=0;enctypes[i];i++) {
diff --git a/source/libads/krb5_errs.c b/source/libads/krb5_errs.c
index e73482522b8..89cfc2d1439 100644
--- a/source/libads/krb5_errs.c
+++ b/source/libads/krb5_errs.c
@@ -50,11 +50,15 @@ static const struct {
{KRB5KRB_AP_ERR_BAD_INTEGRITY, NT_STATUS_LOGON_FAILURE},
{KRB5KRB_AP_ERR_MODIFIED, NT_STATUS_LOGON_FAILURE},
{KRB5KRB_AP_ERR_SKEW, NT_STATUS_TIME_DIFFERENCE_AT_DC},
+ {KRB5_KDCREP_SKEW, NT_STATUS_TIME_DIFFERENCE_AT_DC},
{KRB5KRB_AP_ERR_TKT_EXPIRED, NT_STATUS_LOGON_FAILURE},
{KRB5KRB_ERR_GENERIC, NT_STATUS_UNSUCCESSFUL},
#if defined(KRB5KRB_ERR_RESPONSE_TOO_BIG)
{KRB5KRB_ERR_RESPONSE_TOO_BIG, NT_STATUS_PROTOCOL_UNREACHABLE},
#endif
+ {KRB5_CC_NOTFOUND, NT_STATUS_NO_SUCH_FILE},
+ {KRB5_FCC_NOFILE, NT_STATUS_NO_SUCH_FILE},
+ {KRB5KDC_ERR_NONE, NT_STATUS_OK},
{0, NT_STATUS_OK}
};
diff --git a/source/libads/krb5_setpw.c b/source/libads/krb5_setpw.c
index 07e6320c266..c7a4b982db4 100644
--- a/source/libads/krb5_setpw.c
+++ b/source/libads/krb5_setpw.c
@@ -667,7 +667,9 @@ kerb_prompter(krb5_context ctx, void *data,
memset(prompts[0].reply->data, 0, prompts[0].reply->length);
if (prompts[0].reply->length > 0) {
if (data) {
- strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+ strncpy(prompts[0].reply->data,
+ (const char *)data,
+ prompts[0].reply->length-1);
prompts[0].reply->length = strlen(prompts[0].reply->data);
} else {
prompts[0].reply->length = 0;
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index d4d97cf376b..dfc68fdc2b1 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -47,28 +47,33 @@ static SIG_ATOMIC_T gotalarm;
/***************************************************************
Signal function to tell us we timed out.
****************************************************************/
-
+
static void gotalarm_sig(void)
{
gotalarm = 1;
}
-
+
LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
{
LDAP *ldp = NULL;
-
+
/* Setup timeout */
gotalarm = 0;
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
alarm(to);
/* End setup timeout. */
-
+
ldp = ldap_open(server, port);
-
+
+ if (ldp == NULL) {
+ DEBUG(2,("Could not open LDAP connection to %s:%d: %s\n",
+ server, port, strerror(errno)));
+ }
+
/* Teardown timeout. */
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
alarm(0);
-
+
return ldp;
}
@@ -110,6 +115,54 @@ static int ldap_search_with_timeout(LDAP *ld,
return result;
}
+/**********************************************
+ Do client and server sitename match ?
+**********************************************/
+
+BOOL ads_sitename_match(ADS_STRUCT *ads)
+{
+ if (ads->config.server_site_name == NULL &&
+ ads->config.client_site_name == NULL ) {
+ DEBUG(10,("ads_sitename_match: both null\n"));
+ return True;
+ }
+ if (ads->config.server_site_name &&
+ ads->config.client_site_name &&
+ strequal(ads->config.server_site_name,
+ ads->config.client_site_name)) {
+ DEBUG(10,("ads_sitename_match: name %s match\n", ads->config.server_site_name));
+ return True;
+ }
+ DEBUG(10,("ads_sitename_match: no match between server: %s and client: %s\n",
+ ads->config.server_site_name ? ads->config.server_site_name : "NULL",
+ ads->config.client_site_name ? ads->config.client_site_name : "NULL"));
+ return False;
+}
+
+/**********************************************
+ Is this the closest DC ?
+**********************************************/
+
+BOOL ads_closest_dc(ADS_STRUCT *ads)
+{
+ if (ads->config.flags & ADS_CLOSEST) {
+ DEBUG(10,("ads_closest_dc: ADS_CLOSEST flag set\n"));
+ return True;
+ }
+
+ /* not sure if this can ever happen */
+ if (ads_sitename_match(ads)) {
+ DEBUG(10,("ads_closest_dc: ADS_CLOSEST flag not set but sites match\n"));
+ return True;
+ }
+
+ DEBUG(10,("ads_closest_dc: %s is not the closest DC\n",
+ ads->config.ldap_server_name));
+
+ return False;
+}
+
+
/*
try a connection to a given ldap server, returning True and setting the servers IP
in the ads struct if successful
@@ -134,6 +187,7 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
if ( !ads_cldap_netlogon( srv, ads->server.realm, &cldap_reply ) ) {
DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));
+ SAFE_FREE( srv );
return False;
}
@@ -151,21 +205,32 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
SAFE_FREE(ads->config.realm);
SAFE_FREE(ads->config.bind_path);
SAFE_FREE(ads->config.ldap_server_name);
+ SAFE_FREE(ads->config.server_site_name);
+ SAFE_FREE(ads->config.client_site_name);
SAFE_FREE(ads->server.workgroup);
+ ads->config.flags = cldap_reply.flags;
ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.hostname);
strupper_m(cldap_reply.domain);
ads->config.realm = SMB_STRDUP(cldap_reply.domain);
ads->config.bind_path = ads_build_dn(ads->config.realm);
+ if (*cldap_reply.server_site_name) {
+ ads->config.server_site_name =
+ SMB_STRDUP(cldap_reply.server_site_name);
+ }
+ if (*cldap_reply.client_site_name) {
+ ads->config.client_site_name =
+ SMB_STRDUP(cldap_reply.client_site_name);
+ }
+
ads->server.workgroup = SMB_STRDUP(cldap_reply.netbios_domain);
ads->ldap_port = LDAP_PORT;
ads->ldap_ip = *interpret_addr2(srv);
SAFE_FREE(srv);
- /* cache the successful connection */
-
- saf_store( ads->server.workgroup, server );
+ /* Store our site name. */
+ sitename_store( cldap_reply.domain, cldap_reply.client_site_name );
return True;
}
@@ -176,7 +241,7 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
disabled
**********************************************************************/
-static BOOL ads_find_dc(ADS_STRUCT *ads)
+static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
{
const char *c_realm;
int count, i=0;
@@ -184,6 +249,8 @@ static BOOL ads_find_dc(ADS_STRUCT *ads)
pstring realm;
BOOL got_realm = False;
BOOL use_own_domain = False;
+ char *sitename;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
/* if the realm and workgroup are both empty, assume they are ours */
@@ -201,7 +268,6 @@ static BOOL ads_find_dc(ADS_STRUCT *ads)
if (c_realm && *c_realm)
got_realm = True;
-again:
/* we need to try once with the realm name and fallback to the
netbios domain name if we fail (if netbios has not been disabled */
@@ -214,25 +280,31 @@ again:
if ( !c_realm || !*c_realm ) {
DEBUG(0,("ads_find_dc: no realm or workgroup! Don't know what to do\n"));
- return False;
+ return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */
}
}
pstrcpy( realm, c_realm );
+ sitename = sitename_fetch(realm);
+
+ again:
+
DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
(got_realm ? "realm" : "domain"), realm));
- if ( !get_sorted_dc_list(realm, &ip_list, &count, got_realm) ) {
+ status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm);
+ if (!NT_STATUS_IS_OK(status)) {
/* fall back to netbios if we can */
if ( got_realm && !lp_disable_netbios() ) {
got_realm = False;
goto again;
}
- return False;
+ SAFE_FREE(sitename);
+ return status;
}
-
+
/* if we fail this loop, then giveup since all the IP addresses returned were dead */
for ( i=0; i<count; i++ ) {
fstring server;
@@ -241,10 +313,31 @@ again:
if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )
continue;
+
+ if (!got_realm) {
+ /* realm in this case is a workgroup name. We need
+ to ignore any IP addresses in the negative connection
+ cache that match ip addresses returned in the ad realm
+ case. It sucks that I have to reproduce the logic above... */
+ c_realm = ads->server.realm;
+ if ( !c_realm || !*c_realm ) {
+ if ( !ads->server.workgroup || !*ads->server.workgroup ) {
+ c_realm = lp_realm();
+ }
+ }
+ if (c_realm && *c_realm &&
+ !NT_STATUS_IS_OK(check_negative_conn_cache(c_realm, server))) {
+ /* Ensure we add the workgroup name for this
+ IP address as negative too. */
+ add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );
+ continue;
+ }
+ }
if ( ads_try_connect(ads, server) ) {
SAFE_FREE(ip_list);
- return True;
+ SAFE_FREE(sitename);
+ return NT_STATUS_OK;
}
/* keep track of failures */
@@ -252,8 +345,20 @@ again:
}
SAFE_FREE(ip_list);
-
- return False;
+
+ /* In case we failed to contact one of our closest DC on our site we
+ * need to try to find another DC, retry with a site-less SRV DNS query
+ * - Guenther */
+
+ if (sitename) {
+ DEBUG(1,("ads_find_dc: failed to find a valid DC on our site (%s), "
+ "trying to find another DC\n", sitename));
+ SAFE_FREE(sitename);
+ namecache_delete(realm, 0x1C);
+ goto again;
+ }
+
+ return NT_STATUS_NO_LOGON_SERVERS;
}
@@ -266,6 +371,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
{
int version = LDAP_VERSION3;
ADS_STATUS status;
+ NTSTATUS ntstatus;
ads->last_attempt = time(NULL);
ads->ld = NULL;
@@ -277,11 +383,12 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
goto got_connection;
}
- if (ads_find_dc(ads)) {
+ ntstatus = ads_find_dc(ads);
+ if (NT_STATUS_IS_OK(ntstatus)) {
goto got_connection;
}
- return ADS_ERROR_SYSTEM(errno?errno:ENOENT);
+ return ADS_ERROR_NT(ntstatus);
got_connection:
DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
@@ -325,6 +432,13 @@ got_connection:
{
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
}
+
+ /* cache the successful connection for workgroup and realm */
+ if (ads_closest_dc(ads)) {
+ saf_store( ads->server.workgroup, inet_ntoa(ads->ldap_ip));
+ saf_store( ads->server.realm, inet_ntoa(ads->ldap_ip));
+ }
+
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));
@@ -367,7 +481,8 @@ static struct berval *dup_berval(TALLOC_CTX *ctx, const struct berval *in_val)
if (in_val->bv_len == 0) return value;
value->bv_len = in_val->bv_len;
- value->bv_val = TALLOC_MEMDUP(ctx, in_val->bv_val, in_val->bv_len);
+ value->bv_val = (char *)TALLOC_MEMDUP(ctx, in_val->bv_val,
+ in_val->bv_len);
return value;
}
@@ -446,10 +561,12 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
* @param cookie The paged results cookie to be returned on subsequent calls
* @return status of search
**/
-ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads,
+ const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res,
+ int *count, struct berval **cookie)
{
int rc, i, version;
char *utf8_expr, *utf8_path, **search_attrs;
@@ -622,10 +739,10 @@ done:
return ADS_ERROR(rc);
}
-ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res,
+ int *count, struct berval **cookie)
{
return ads_do_paged_search_args(ads, bind_path, scope, expr, attrs, NULL, res, count, cookie);
}
@@ -642,11 +759,12 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res)
+ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
@@ -659,7 +777,7 @@ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
#ifdef HAVE_LDAP_ADD_RESULT_ENTRY
while (cookie) {
- void *res2 = NULL;
+ LDAPMessage *res2 = NULL;
ADS_STATUS status2;
LDAPMessage *msg, *next;
@@ -685,9 +803,9 @@ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
return status;
}
-ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res)
{
return ads_do_search_all_args(ads, bind_path, scope, expr, attrs, NULL, res);
}
@@ -709,10 +827,10 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
BOOL(*fn)(char *, void **, void *),
void *data_area)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_paged_search(ads, bind_path, scope, expr, attrs, &res,
&count, &cookie);
@@ -745,9 +863,9 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res)
{
int rc;
char *utf8_expr, *utf8_path, **search_attrs = NULL;
@@ -809,9 +927,8 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
- const char *expr,
- const char **attrs)
+ ADS_STATUS ads_search(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs)
{
return ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
expr, attrs, res);
@@ -825,11 +942,11 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs)
+ ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn, const char **attrs)
{
- return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res);
+ return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)",
+ attrs, res);
}
/**
@@ -837,7 +954,7 @@ ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void **res,
* @param ads connection to ads server
* @param msg Search results to free
**/
-void ads_msgfree(ADS_STRUCT *ads, void *msg)
+ void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg)
{
if (!msg) return;
ldap_msgfree(msg);
@@ -859,7 +976,7 @@ void ads_memfree(ADS_STRUCT *ads, void *mem)
* @param msg Search result
* @return dn string
**/
-char *ads_get_dn(ADS_STRUCT *ads, void *msg)
+ char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg)
{
char *utf8_dn, *unix_dn;
@@ -880,21 +997,6 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
}
/**
- * Get a canonical dn from search results
- * @param ads connection to ads server
- * @param msg Search result
- * @return dn string
- **/
-char *ads_get_dn_canonical(ADS_STRUCT *ads, void *msg)
-{
-#ifdef HAVE_LDAP_DN2AD_CANONICAL
- return ldap_dn2ad_canonical(ads_get_dn(ads, msg));
-#else
- return NULL;
-#endif
-}
-
-/**
* Get the parent from a dn
* @param dn the dn to return the parent from
* @return parent dn string
@@ -923,7 +1025,8 @@ char *ads_parent_dn(const char *dn)
* @param host Hostname to search for
* @return status of search
**/
-ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *machine)
+ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *machine)
{
ADS_STATUS status;
char *expr;
@@ -967,8 +1070,9 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx)
*/
static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
int mod_op, const char *name,
- const void **invals)
+ const void *_invals)
{
+ const void **invals = (const void **)_invals;
int curmod;
LDAPMod **modlist = (LDAPMod **) *mods;
struct berval **ber_values = NULL;
@@ -1031,8 +1135,7 @@ ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods,
if (!val)
return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL);
- return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name,
- (const void **) values);
+ return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, values);
}
/**
@@ -1200,8 +1303,9 @@ char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit)
char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
{
ADS_STATUS status;
- void *res = NULL;
- char *base, *wkn_dn = NULL, *ret = NULL, **wkn_dn_exp = NULL, **bind_dn_exp = NULL;
+ LDAPMessage *res = NULL;
+ char *base, *wkn_dn = NULL, *ret = NULL, **wkn_dn_exp = NULL,
+ **bind_dn_exp = NULL;
const char *attrs[] = {"distinguishedName", NULL};
int new_ln, wkn_ln, bind_ln, i;
@@ -1295,7 +1399,8 @@ char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
const char *name, const char **vals)
{
- return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name, (const void **) vals);
+ return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name,
+ (const void *) vals);
}
/**
@@ -1318,7 +1423,7 @@ uint32 ads_get_kvno(ADS_STRUCT *ads, const char *machine_name)
if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
return kvno;
}
- ret = ads_search(ads, (void**)(void *)&res, filter, attrs);
+ ret = ads_search(ads, &res, filter, attrs);
SAFE_FREE(filter);
if (!ADS_ERR_OK(ret) && ads_count_replies(ads, res)) {
DEBUG(1,("ads_get_kvno: Computer Account For %s not found.\n", machine_name));
@@ -1372,7 +1477,7 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin
ADS_STATUS ret = ADS_ERROR(LDAP_SUCCESS);
char *dn_string = NULL;
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(5,("ads_clear_service_principal_names: WARNING: Host Account for %s not found... skipping operation.\n", machine_name));
DEBUG(5,("ads_clear_service_principal_names: WARNING: Service Principals for %s have NOT been cleared.\n", machine_name));
@@ -1441,7 +1546,7 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n
char *dn_string = NULL;
const char *servicePrincipalName[3] = {NULL, NULL, NULL};
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(1,("ads_add_service_principal_name: WARNING: Host Account for %s not found... skipping operation.\n",
machine_name));
@@ -1676,6 +1781,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
{"tokenGroups", False, dump_sid},
{"tokenGroupsNoGCAcceptable", False, dump_sid},
{"tokengroupsGlobalandUniversal", False, dump_sid},
+ {"mS-DS-CreatorSID", False, dump_sid},
{NULL, True, NULL}
};
int i;
@@ -1708,7 +1814,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
* @param res Results to dump
**/
-void ads_dump(ADS_STRUCT *ads, void *res)
+ void ads_dump(ADS_STRUCT *ads, LDAPMessage *res)
{
ads_process_results(ads, res, ads_dump_field, NULL);
}
@@ -1724,11 +1830,11 @@ void ads_dump(ADS_STRUCT *ads, void *res)
* @param fn Function for processing each result
* @param data_area user-defined area to pass to function
**/
-void ads_process_results(ADS_STRUCT *ads, void *res,
- BOOL(*fn)(char *, void **, void *),
- void *data_area)
+ void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
+ BOOL(*fn)(char *, void **, void *),
+ void *data_area)
{
- void *msg;
+ LDAPMessage *msg;
TALLOC_CTX *ctx;
if (!(ctx = talloc_init("ads_process_results")))
@@ -1793,9 +1899,9 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
* @param res Results of search
* @return first entry from result
**/
-void *ads_first_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_first_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_first_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_first_entry(ads->ld, res);
}
/**
@@ -1804,9 +1910,9 @@ void *ads_first_entry(ADS_STRUCT *ads, void *res)
* @param res Results of search
* @return next entry from result
**/
-void *ads_next_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_next_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_next_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_next_entry(ads->ld, res);
}
/**
@@ -1817,8 +1923,8 @@ void *ads_next_entry(ADS_STRUCT *ads, void *res)
* @param field Attribute to retrieve
* @return Result string in talloc context
**/
-char *ads_pull_string(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field)
+ char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
+ const char *field)
{
char **values;
char *ret = NULL;
@@ -1848,9 +1954,9 @@ char *ads_pull_string(ADS_STRUCT *ads,
* @param field Attribute to retrieve
* @return Result strings in talloc context
**/
-char **ads_pull_strings(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field,
- size_t *num_values)
+ char **ads_pull_strings(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ size_t *num_values)
{
char **values;
char **ret = NULL;
@@ -1893,13 +1999,13 @@ char **ads_pull_strings(ADS_STRUCT *ads,
* @param more_values Are there more values to get?
* @return Result strings in talloc context
**/
-char **ads_pull_strings_range(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg, const char *field,
- char **current_strings,
- const char **next_attribute,
- size_t *num_strings,
- BOOL *more_strings)
+ char **ads_pull_strings_range(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ char **current_strings,
+ const char **next_attribute,
+ size_t *num_strings,
+ BOOL *more_strings)
{
char *attr;
char *expected_range_attrib, *range_attr;
@@ -2016,8 +2122,8 @@ char **ads_pull_strings_range(ADS_STRUCT *ads,
* @param v Pointer to int to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_uint32(ADS_STRUCT *ads,
- void *msg, const char *field, uint32 *v)
+ BOOL ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ uint32 *v)
{
char **values;
@@ -2041,8 +2147,7 @@ BOOL ads_pull_uint32(ADS_STRUCT *ads,
* @param guid 37-byte area to receive text guid
* @return boolean indicating success
**/
-BOOL ads_pull_guid(ADS_STRUCT *ads,
- void *msg, struct uuid *guid)
+ BOOL ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid)
{
char **values;
UUID_FLAT flat_guid;
@@ -2071,8 +2176,8 @@ BOOL ads_pull_guid(ADS_STRUCT *ads,
* @param sid Pointer to sid to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_sid(ADS_STRUCT *ads,
- void *msg, const char *field, DOM_SID *sid)
+ BOOL ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ DOM_SID *sid)
{
struct berval **values;
BOOL ret = False;
@@ -2098,8 +2203,8 @@ BOOL ads_pull_sid(ADS_STRUCT *ads,
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, DOM_SID **sids)
+ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, DOM_SID **sids)
{
struct berval **values;
BOOL ret;
@@ -2142,8 +2247,8 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
* @param sd Pointer to *SEC_DESC to store result (talloc()ed)
* @return boolean inidicating success
*/
-BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, SEC_DESC **sd)
+ BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, SEC_DESC **sd)
{
struct berval **values;
prs_struct ps;
@@ -2175,7 +2280,8 @@ BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
* @param msg Results of search
* @return the username
*/
-char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg)
+ char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg)
{
#if 0 /* JERRY */
char *ret, *p;
@@ -2205,7 +2311,7 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
{
const char *attrs[] = {"highestCommittedUSN", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_search_retry(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status))
@@ -2252,7 +2358,7 @@ ADS_STATUS ads_current_time(ADS_STRUCT *ads)
{
const char *attrs[] = {"currentTime", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
char *timestr;
TALLOC_CTX *ctx;
ADS_STRUCT *ads_s = ads;
@@ -2317,7 +2423,7 @@ ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val)
{
const char *attrs[] = {"domainFunctionality", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
ADS_STRUCT *ads_s = ads;
*val = DS_DOMAIN_FUNCTION_2000;
@@ -2373,7 +2479,7 @@ done:
ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
{
const char *attrs[] = {"objectSid", NULL};
- void *res;
+ LDAPMessage *res;
ADS_STATUS rc;
rc = ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
@@ -2398,7 +2504,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *dn, *service_name;
const char *attrs[] = { "dsServiceName", NULL };
@@ -2409,9 +2515,12 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
if (service_name == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
+ ads_msgfree(ads, res);
+
/* go up three levels */
dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
if (dn == NULL) {
@@ -2423,8 +2532,6 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads_msgfree(ads, res);
-
return status;
/*
dsServiceName: CN=NTDS Settings,CN=W2K3DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=ber,DC=suse,DC=de
@@ -2442,7 +2549,7 @@ ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_n
ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *computer_name, const char **site_dn)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *parent, *config_context, *filter;
const char *attrs[] = { "configurationNamingContext", NULL };
char *dn;
@@ -2459,37 +2566,45 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
if (config_context == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
if (filter == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &res);
if (!ADS_ERR_OK(status)) {
return status;
}
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
/* go up three levels */
parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
if (parent == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
*site_dn = talloc_strdup(mem_ctx, parent);
if (*site_dn == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
ADS_ERROR(LDAP_NO_MEMORY);
}
@@ -2505,13 +2620,13 @@ ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const c
* @param ads connection to ads server
* @param mem_ctx Pointer to talloc context
* @param suffixes Pointer to an array of suffixes
- * @param site_name Pointer to the number of suffixes
+ * @param num_suffixes Pointer to the number of suffixes
* @return status of search
**/
-ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
+ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char ***suffixes, size_t *num_suffixes)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *config_context, *base;
const char *attrs[] = { "configurationNamingContext", NULL };
const char *attrs2[] = { "uPNSuffixes", NULL };
@@ -2523,9 +2638,12 @@ ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixe
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
if (config_context == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
if (base == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -2540,8 +2658,8 @@ ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixe
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
- suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
- if (suffixes == NULL) {
+ (*suffixes) = ads_pull_strings(ads, mem_ctx, res, "uPNSuffixes", num_suffixes);
+ if ((*suffixes) == NULL) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
@@ -2637,12 +2755,12 @@ BOOL ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg,
- const char *field,
- enum ads_extended_dn_flags flags,
- DOM_SID **sids)
+ int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids)
{
int i;
size_t dn_count;
@@ -2684,7 +2802,7 @@ char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
@@ -2716,20 +2834,20 @@ char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name )
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
- DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
+ DEBUG(0,("ads_get_upn: Failed to find account for %s\n",
global_myname()));
goto out;
}
if ( (count = ads_count_replies(ads, res)) != 1 ) {
- DEBUG(1,("ads_get_dnshostname: %d entries returned!\n", count));
+ DEBUG(1,("ads_get_upn: %d entries returned!\n", count));
goto out;
}
if ( (name = ads_pull_string(ads, ctx, res, "userPrincipalName")) == NULL ) {
- DEBUG(0,("ads_get_dnshostname: No userPrincipalName attribute!\n"));
+ DEBUG(2,("ads_get_upn: No userPrincipalName attribute!\n"));
}
out:
@@ -2748,7 +2866,7 @@ char* ads_get_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *mach
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
@@ -2770,4 +2888,180 @@ out:
return name;
}
+#if 0
+
+ SAVED CODE - we used to join via ldap - remember how we did this. JRA.
+
+/**
+ * Join a machine to a realm
+ * Creates the machine account and sets the machine password
+ * @param ads connection to ads server
+ * @param machine name of host to add
+ * @param org_unit Organizational unit to place machine in
+ * @return status of join
+ **/
+ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
+ uint32 account_type, const char *org_unit)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ char *machine;
+
+ /* machine name must be lowercase */
+ machine = SMB_STRDUP(machine_name);
+ strlower_m(machine);
+
+ /*
+ status = ads_find_machine_acct(ads, (void **)&res, machine);
+ if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
+ DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine));
+ status = ads_leave_realm(ads, machine);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
+ machine, ads->config.realm));
+ return status;
+ }
+ }
+ */
+ status = ads_add_machine_acct(ads, machine, account_type, org_unit);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("ads_join_realm: ads_add_machine_acct failed (%s): %s\n", machine, ads_errstr(status)));
+ SAFE_FREE(machine);
+ return status;
+ }
+
+ status = ads_find_machine_acct(ads, (void **)(void *)&res, machine);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("ads_join_realm: Host account test failed for machine %s\n", machine));
+ SAFE_FREE(machine);
+ return status;
+ }
+
+ SAFE_FREE(machine);
+ ads_msgfree(ads, res);
+
+ return status;
+}
+#endif
+
+/**
+ * Delete a machine from the realm
+ * @param ads connection to ads server
+ * @param hostname Machine to remove
+ * @return status of delete
+ **/
+ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
+{
+ ADS_STATUS status;
+ void *msg;
+ LDAPMessage *res;
+ char *hostnameDN, *host;
+ int rc;
+ LDAPControl ldap_control;
+ LDAPControl * pldap_control[2] = {NULL, NULL};
+
+ pldap_control[0] = &ldap_control;
+ memset(&ldap_control, 0, sizeof(LDAPControl));
+ ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID;
+
+ /* hostname must be lowercase */
+ host = SMB_STRDUP(hostname);
+ strlower_m(host);
+
+ status = ads_find_machine_acct(ads, &res, host);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Host account for %s does not exist.\n", host));
+ SAFE_FREE(host);
+ return status;
+ }
+
+ msg = ads_first_entry(ads, res);
+ if (!msg) {
+ SAFE_FREE(host);
+ return ADS_ERROR_SYSTEM(ENOENT);
+ }
+
+ hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg);
+
+ rc = ldap_delete_ext_s(ads->ld, hostnameDN, pldap_control, NULL);
+ if (rc) {
+ DEBUG(3,("ldap_delete_ext_s failed with error code %d\n", rc));
+ }else {
+ DEBUG(3,("ldap_delete_ext_s succeeded with error code %d\n", rc));
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ const char *attrs[] = { "cn", NULL };
+ LDAPMessage *msg_sub;
+
+ /* we only search with scope ONE, we do not expect any further
+ * objects to be created deeper */
+
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ for (msg_sub = ads_first_entry(ads, res); msg_sub;
+ msg_sub = ads_next_entry(ads, msg_sub)) {
+
+ char *dn = NULL;
+
+ if ((dn = ads_get_dn(ads, msg_sub)) == NULL) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_del_dn(ads, dn);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("failed to delete dn %s: %s\n", dn, ads_errstr(status)));
+ SAFE_FREE(host);
+ ads_memfree(ads, dn);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ ads_memfree(ads, dn);
+ }
+
+ /* there should be no subordinate objects anymore */
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
+
+ if (!ADS_ERR_OK(status) || ( (ads_count_replies(ads, res)) > 0 ) ) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ /* delete hostnameDN now */
+ status = ads_del_dn(ads, hostnameDN);
+ if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(host);
+ DEBUG(3,("failed to delete dn %s: %s\n", hostnameDN, ads_errstr(status)));
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+ }
+
+ ads_memfree(ads, hostnameDN);
+
+ status = ads_find_machine_acct(ads, &res, host);
+ if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
+ DEBUG(3, ("Failed to remove host account.\n"));
+ SAFE_FREE(host);
+ return status;
+ }
+
+ SAFE_FREE(host);
+ return status;
+}
+
#endif
diff --git a/source/libads/ldap_printer.c b/source/libads/ldap_printer.c
index 2d2664979cd..f5168b05af0 100644
--- a/source/libads/ldap_printer.c
+++ b/source/libads/ldap_printer.c
@@ -27,8 +27,9 @@
Note that results "res" may be allocated on return so that the
results can be used. It should be freed using ads_msgfree.
*/
-ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
- const char *printer, const char *servername)
+ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *printer,
+ const char *servername)
{
ADS_STATUS status;
char *srv_dn, **srv_cn, *s;
@@ -63,7 +64,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
return status;
}
-ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
+ ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
{
const char *ldap_expr;
const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
diff --git a/source/libads/ldap_schema.c b/source/libads/ldap_schema.c
index e63a888b5b9..5d91d985490 100644
--- a/source/libads/ldap_schema.c
+++ b/source/libads/ldap_schema.c
@@ -29,7 +29,7 @@ ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
char ***OIDs_out, char ***names, size_t *count)
{
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
LDAPMessage *msg;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
@@ -111,7 +111,7 @@ const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TA
{
ADS_STATUS rc;
int count = 0;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *expr = NULL;
const char *attrs[] = { "lDAPDisplayName", NULL };
char *result;
@@ -155,7 +155,7 @@ failed:
static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *schema;
const char *attrs[] = { "schemaNamingContext", NULL };
@@ -165,10 +165,12 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
}
if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
@@ -184,7 +186,10 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
* @return ADS_STATUS status of search (False if one or more attributes couldn't be
* found in Active Directory)
**/
-ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type)
+ADS_STATUS ads_check_posix_schema_mapping(TALLOC_CTX *mem_ctx,
+ ADS_STRUCT *ads,
+ enum wb_posix_mapping map_type,
+ struct posix_schema **s )
{
TALLOC_CTX *ctx = NULL;
ADS_STATUS status;
@@ -192,6 +197,7 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
size_t num_names;
char *schema_path = NULL;
int i;
+ struct posix_schema *schema = NULL;
const char *oids_sfu[] = { ADS_ATTR_SFU_UIDNUMBER_OID,
ADS_ATTR_SFU_GIDNUMBER_OID,
@@ -207,34 +213,15 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
DEBUG(10,("ads_check_posix_schema_mapping\n"));
- switch (map_type) {
-
- case WB_POSIX_MAP_TEMPLATE:
- case WB_POSIX_MAP_UNIXINFO:
- DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n"));
- return ADS_ERROR(LDAP_SUCCESS);
-
- case WB_POSIX_MAP_SFU:
- case WB_POSIX_MAP_RFC2307:
- break;
-
- default:
- DEBUG(0,("ads_check_posix_schema_mapping: "
- "unknown enum %d\n", map_type));
- return ADS_ERROR(LDAP_PARAM_ERROR);
+ if ( (ctx = talloc_init("ads_check_posix_schema_mapping")) == NULL ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads->schema.posix_uidnumber_attr = NULL;
- ads->schema.posix_gidnumber_attr = NULL;
- ads->schema.posix_homedir_attr = NULL;
- ads->schema.posix_shell_attr = NULL;
- ads->schema.posix_gecos_attr = NULL;
-
- ctx = talloc_init("ads_check_posix_schema_mapping");
- if (ctx == NULL) {
+ if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) {
+ TALLOC_FREE( ctx );
return ADS_ERROR(LDAP_NO_MEMORY);
}
-
+
status = ads_schema_path(ads, ctx, &schema_path);
if (!ADS_ERR_OK(status)) {
DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
@@ -255,10 +242,7 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n",
ads_errstr(status)));
goto done;
- }
-
- DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
- wb_posix_map_str(map_type)));
+ }
for (i=0; i<num_names; i++) {
@@ -266,43 +250,48 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i])) {
- SAFE_FREE(ads->schema.posix_uidnumber_attr);
- ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
+ schema->posix_uidnumber_attr = talloc_strdup(schema, names_out[i]);
+ continue;
}
+
if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
- SAFE_FREE(ads->schema.posix_gidnumber_attr);
- ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
+ schema->posix_gidnumber_attr = talloc_strdup(schema, names_out[i]);
+ continue;
}
+
if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
- SAFE_FREE(ads->schema.posix_homedir_attr);
- ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
+ schema->posix_homedir_attr = talloc_strdup(schema, names_out[i]);
+ continue;
}
+
if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
- SAFE_FREE(ads->schema.posix_shell_attr);
- ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
+ schema->posix_shell_attr = talloc_strdup(schema, names_out[i]);
+ continue;
}
+
if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
- SAFE_FREE(ads->schema.posix_gecos_attr);
- ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
+ schema->posix_gecos_attr = talloc_strdup(schema, names_out[i]);
}
}
- if (!ads->schema.posix_uidnumber_attr ||
- !ads->schema.posix_gidnumber_attr ||
- !ads->schema.posix_homedir_attr ||
- !ads->schema.posix_shell_attr ||
- !ads->schema.posix_gecos_attr) {
+ if (!schema->posix_uidnumber_attr ||
+ !schema->posix_gidnumber_attr ||
+ !schema->posix_homedir_attr ||
+ !schema->posix_shell_attr ||
+ !schema->posix_gecos_attr) {
status = ADS_ERROR(LDAP_NO_MEMORY);
+ TALLOC_FREE( schema );
goto done;
}
+
+ *s = schema;
status = ADS_ERROR(LDAP_SUCCESS);
- ads->schema.map_type = map_type;
done:
if (ctx) {
talloc_destroy(ctx);
diff --git a/source/libads/ldap_user.c b/source/libads/ldap_user.c
index 3ff6acc9e83..66d94d29d3a 100644
--- a/source/libads/ldap_user.c
+++ b/source/libads/ldap_user.c
@@ -25,7 +25,8 @@
/*
find a user account
*/
-ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
+ ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *user)
{
ADS_STATUS status;
char *ldap_exp;
diff --git a/source/libads/ldap_utils.c b/source/libads/ldap_utils.c
index 03ae94150f4..4edd73c18d7 100644
--- a/source/libads/ldap_utils.c
+++ b/source/libads/ldap_utils.c
@@ -29,7 +29,8 @@
*/
static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind_path, int scope,
const char *expr,
- const char **attrs, void *args, void **res)
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
ADS_STATUS status = ADS_SUCCESS;
int count = 3;
@@ -59,8 +60,8 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res);
}
if (ADS_ERR_OK(status)) {
- DEBUG(5,("Search for %s gave %d replies\n",
- expr, ads_count_replies(ads, *res)));
+ DEBUG(5,("Search for %s in <%s> gave %d replies\n",
+ expr, bp, ads_count_replies(ads, *res)));
SAFE_FREE(bp);
return status;
}
@@ -109,48 +110,48 @@ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind
}
SAFE_FREE(bp);
- if (!ADS_ERR_OK(status))
+ if (!ADS_ERR_OK(status)) {
DEBUG(1,("ads reopen failed after error %s\n",
ads_errstr(status)));
-
+ }
return status;
}
-ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res)
{
return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, NULL, res);
}
-ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void *args, void **res)
+ ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, args, res);
}
-ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
- const char *expr,
- const char **attrs)
+ ADS_STATUS ads_search_retry(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs)
{
return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
expr, attrs, res);
}
-ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs)
+ ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs)
{
return ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE,
"(objectclass=*)", attrs, res);
}
-ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, void **res,
- const char *dn,
- const char **attrs,
- enum ads_extended_dn_flags flags)
+ ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn,
+ const char **attrs,
+ enum ads_extended_dn_flags flags)
{
ads_control args;
@@ -162,9 +163,9 @@ ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, void **res,
"(objectclass=*)", attrs, &args, res);
}
-ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, void **res,
- const DOM_SID *sid,
- const char **attrs)
+ ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, LDAPMessage **res,
+ const DOM_SID *sid,
+ const char **attrs)
{
char *dn, *sid_string;
ADS_STATUS status;
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 52a0f0b165c..812f3961f19 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -136,6 +136,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
return ADS_ERROR(rc);
}
+#ifdef HAVE_KRB5
/*
perform a LDAP/SASL/SPNEGO/KRB5 bind
*/
@@ -146,7 +147,8 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
DATA_BLOB session_key = data_blob(NULL, 0);
int rc;
- rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0);
+ rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
+ &ads->auth.tgs_expire);
if (rc) {
return ADS_ERROR_KRB5(rc);
@@ -165,6 +167,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
return ADS_ERROR(rc);
}
+#endif
/*
this performs a SASL/SPNEGO bind
@@ -216,17 +219,48 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
#endif
free(OIDs[i]);
}
- DEBUG(3,("ads_sasl_spnego_bind: got server principal name =%s\n", principal));
+ DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", principal));
#ifdef HAVE_KRB5
if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
- got_kerberos_mechanism) {
+ got_kerberos_mechanism)
+ {
+ /* I've seen a child Windows 2000 domain not send
+ the principal name back in the first round of
+ the SASL bind reply. So we guess based on server
+ name and realm. --jerry */
+ if ( !principal ) {
+ if ( ads->server.realm && ads->server.ldap_server ) {
+ char *server, *server_realm;
+
+ server = SMB_STRDUP( ads->server.ldap_server );
+ server_realm = SMB_STRDUP( ads->server.realm );
+
+ if ( !server || !server_realm )
+ return ADS_ERROR(LDAP_NO_MEMORY);
+
+ strlower_m( server );
+ strupper_m( server_realm );
+ asprintf( &principal, "ldap/%s@%s", server, server_realm );
+
+ SAFE_FREE( server );
+ SAFE_FREE( server_realm );
+
+ if ( !principal )
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ }
+
status = ads_sasl_spnego_krb5_bind(ads, principal);
if (ADS_ERR_OK(status)) {
SAFE_FREE(principal);
return status;
}
+ DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
+ "calling kinit\n", ads_errstr(status)));
+
status = ADS_ERROR_KRB5(ads_kinit_password(ads));
if (ADS_ERR_OK(status)) {
@@ -348,7 +382,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
goto failed;
}
- cred.bv_val = output_token.value;
+ cred.bv_val = (char *)output_token.value;
cred.bv_len = output_token.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL,
@@ -389,6 +423,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
#if 0
file_save("sasl_gssapi.dat", output_token.value, output_token.length);
#endif
+
if (p) {
max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
}
@@ -396,7 +431,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_buffer(&minor_status, &output_token);
output_token.value = SMB_MALLOC(strlen(ads->config.bind_path) + 8);
- p = output_token.value;
+ p = (uint8 *)output_token.value;
*p++ = 1; /* no sign & seal selection */
/* choose the same size as the server gave us */
@@ -418,7 +453,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
free(output_token.value);
- cred.bv_val = input_token.value;
+ cred.bv_val = (char *)input_token.value;
cred.bv_len = input_token.length;
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL,
@@ -452,7 +487,7 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
char **values;
ADS_STATUS status;
int i, j;
- void *res;
+ LDAPMessage *res;
/* get a list of supported SASL mechanisms */
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
diff --git a/source/libgpo/gpo_fetch.c b/source/libgpo/gpo_fetch.c
new file mode 100644
index 00000000000..3347a36b07e
--- /dev/null
+++ b/source/libgpo/gpo_fetch.c
@@ -0,0 +1,194 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2005-2006
+ *
+ * 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"
+
+/****************************************************************
+ explode the GPO CIFS URI into their components
+****************************************************************/
+
+NTSTATUS ads_gpo_explode_filesyspath(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *file_sys_path,
+ char **server,
+ char **service,
+ char **nt_path,
+ char **unix_path)
+{
+ fstring tok;
+ pstring path;
+
+ *server = NULL;
+ *service = NULL;
+ *nt_path = NULL;
+ *unix_path = NULL;
+
+ if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((*server = talloc_strdup(mem_ctx, tok)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((*service = talloc_strdup(mem_ctx, tok)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ((*nt_path = talloc_asprintf(mem_ctx, "\\%s", file_sys_path)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pstrcpy(path, lock_path(GPO_CACHE_DIR));
+ pstrcat(path, "/");
+ pstrcat(path, file_sys_path);
+ pstring_sub(path, "\\", "/");
+
+ if ((*unix_path = talloc_strdup(mem_ctx, path)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ prepare the local disc storage for "unix_path"
+****************************************************************/
+
+NTSTATUS ads_gpo_prepare_local_store(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *unix_path)
+{
+ const char *top_dir = lock_path(GPO_CACHE_DIR);
+ char *current_dir;
+ fstring tok;
+
+ current_dir = talloc_strdup(mem_ctx, top_dir);
+ NT_STATUS_HAVE_NO_MEMORY(current_dir);
+
+ if ((mkdir(top_dir, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ while (next_token(&unix_path, tok, "/", sizeof(tok))) {
+
+ if (strequal(tok, GPO_CACHE_DIR)) {
+ break;
+ }
+ }
+
+ while (next_token(&unix_path, tok, "/", sizeof(tok))) {
+
+ current_dir = talloc_asprintf_append(current_dir, "/%s", tok);
+ NT_STATUS_HAVE_NO_MEMORY(current_dir);
+
+ if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ download a full GPO via CIFS
+****************************************************************/
+
+NTSTATUS ads_fetch_gpo_files(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ struct GROUP_POLICY_OBJECT *gpo)
+{
+ NTSTATUS result;
+ char *server, *service, *nt_path, *unix_path, *nt_ini_path, *unix_ini_path;
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &service, &nt_path, &unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_prepare_local_store(ads, mem_ctx, unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ unix_ini_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
+ nt_ini_path = talloc_asprintf(mem_ctx, "%s\\%s", nt_path, GPT_INI);
+ if (!unix_path || !nt_ini_path) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ result = gpo_copy_file(mem_ctx, cli, nt_ini_path, unix_ini_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = gpo_sync_directories(mem_ctx, cli, nt_path, unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ return result;
+}
+
+/****************************************************************
+ get the locally stored gpt.ini version number
+****************************************************************/
+
+NTSTATUS ads_gpo_get_sysvol_gpt_version(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *unix_path,
+ uint32 *sysvol_version,
+ char **display_name)
+{
+ NTSTATUS status;
+ uint32 version;
+ char *local_path = NULL;
+ char *name = NULL;
+
+ local_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
+ NT_STATUS_HAVE_NO_MEMORY(local_path);
+
+ status = parse_gpt_ini(mem_ctx, local_path, &version, &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("ads_gpo_get_sysvol_gpt_version: failed to parse ini [%s]: %s\n",
+ unix_path, nt_errstr(status)));
+ return status;
+ }
+
+ if (sysvol_version) {
+ *sysvol_version = version;
+ }
+
+ if (name && *display_name) {
+ *display_name = talloc_strdup(mem_ctx, name);
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source/libgpo/gpo_filesync.c b/source/libgpo/gpo_filesync.c
new file mode 100644
index 00000000000..e97562c93f3
--- /dev/null
+++ b/source/libgpo/gpo_filesync.c
@@ -0,0 +1,225 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2006
+ *
+ * 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"
+
+struct sync_context {
+ TALLOC_CTX *mem_ctx;
+ struct cli_state *cli;
+ char *remote_path;
+ char *local_path;
+ pstring mask;
+ uint16 attribute;
+};
+
+static void gpo_sync_func(const char *mnt,
+ file_info *info,
+ const char *mask,
+ void *state);
+
+NTSTATUS gpo_copy_file(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ const char *nt_path,
+ const char *unix_path)
+{
+ NTSTATUS result;
+ int fnum;
+ int fd = 0;
+ char *data = NULL;
+ static int io_bufsize = 64512;
+ int read_size = io_bufsize;
+ off_t start = 0;
+ off_t nread = 0;
+
+ if ((fnum = cli_open(cli, nt_path, O_RDONLY, DENY_NONE)) == -1) {
+ result = NT_STATUS_NO_SUCH_FILE;
+ goto out;
+ }
+
+ if ((fd = sys_open(unix_path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+ result = map_nt_error_from_unix(errno);
+ goto out;
+ }
+
+ if ((data = (char *)SMB_MALLOC(read_size)) == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ while (1) {
+
+ int n = cli_read(cli, fnum, data, nread + start, read_size);
+
+ if (n <= 0)
+ break;
+
+ if (write(fd, data, n) != n) {
+ break;
+ }
+
+ nread += n;
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ SAFE_FREE(data);
+ if (fnum) {
+ cli_close(cli, fnum);
+ }
+ if (fd) {
+ close(fd);
+ }
+
+ return result;
+}
+
+/****************************************************************
+ copy dir
+****************************************************************/
+
+static NTSTATUS gpo_copy_dir(const char *unix_path)
+{
+ if ((mkdir(unix_path, 0644)) < 0 && errno != EEXIST) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ sync files
+****************************************************************/
+
+static BOOL gpo_sync_files(struct sync_context *ctx)
+{
+ DEBUG(3,("calling cli_list with mask: %s\n", ctx->mask));
+
+ if (cli_list(ctx->cli, ctx->mask, ctx->attribute, gpo_sync_func, ctx) == -1) {
+ DEBUG(1,("listing [%s] failed with error: %s\n",
+ ctx->mask, cli_errstr(ctx->cli)));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************
+ syncronisation call back
+****************************************************************/
+
+static void gpo_sync_func(const char *mnt,
+ file_info *info,
+ const char *mask,
+ void *state)
+{
+ NTSTATUS result;
+ struct sync_context *ctx;
+ fstring nt_filename, unix_filename;
+ fstring nt_dir, unix_dir;
+ char *old_nt_dir, *old_unix_dir;
+
+ ctx = (struct sync_context *)state;
+
+ if (strequal(info->name, ".") || strequal(info->name, "..")) {
+ return;
+ }
+
+ DEBUG(5,("gpo_sync_func: got mask: [%s], name: [%s]\n",
+ mask, info->name));
+
+ if (info->mode & aDIR) {
+
+ DEBUG(3,("got dir: [%s]\n", info->name));
+
+ fstrcpy(nt_dir, ctx->remote_path);
+ fstrcat(nt_dir, "\\");
+ fstrcat(nt_dir, info->name);
+
+ fstrcpy(unix_dir, ctx->local_path);
+ fstrcat(unix_dir, "/");
+ fstrcat(unix_dir, info->name);
+
+ result = gpo_copy_dir(unix_dir);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed to copy dir: %s\n", nt_errstr(result)));
+ }
+
+ old_nt_dir = ctx->remote_path;
+ ctx->remote_path = nt_dir;
+
+ old_unix_dir = ctx->local_path;
+ ctx->local_path = talloc_strdup(ctx->mem_ctx, unix_dir);
+
+ pstrcpy(ctx->mask, nt_dir);
+ pstrcat(ctx->mask, "\\*");
+
+ if (!gpo_sync_files(ctx)) {
+ DEBUG(0,("could not sync files\n"));
+ }
+
+ ctx->remote_path = old_nt_dir;
+ ctx->local_path = old_unix_dir;
+ return;
+ }
+
+ DEBUG(3,("got file: [%s]\n", info->name));
+
+ fstrcpy(nt_filename, ctx->remote_path);
+ fstrcat(nt_filename, "\\");
+ fstrcat(nt_filename, info->name);
+
+ fstrcpy(unix_filename, ctx->local_path);
+ fstrcat(unix_filename, "/");
+ fstrcat(unix_filename, info->name);
+
+ result = gpo_copy_file(ctx->mem_ctx, ctx->cli, nt_filename, unix_filename);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed to copy file: %s\n", nt_errstr(result)));
+ }
+}
+
+
+/****************************************************************
+ list a remote directory and download recursivly
+****************************************************************/
+
+NTSTATUS gpo_sync_directories(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ const char *nt_path,
+ const char *local_path)
+{
+ struct sync_context ctx;
+
+ ctx.mem_ctx = mem_ctx;
+ ctx.cli = cli;
+ ctx.remote_path = CONST_DISCARD(char *, nt_path);
+ ctx.local_path = CONST_DISCARD(char *, local_path);
+ ctx.attribute = (aSYSTEM | aHIDDEN | aDIR);
+
+ pstrcpy(ctx.mask, nt_path);
+ pstrcat(ctx.mask, "\\*");
+
+ if (!gpo_sync_files(&ctx)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source/libads/gpo.c b/source/libgpo/gpo_ldap.c
index 9cf7aae9770..13ec80f2ad2 100644
--- a/source/libads/gpo.c
+++ b/source/libgpo/gpo_ldap.c
@@ -20,12 +20,18 @@
#include "includes.h"
+#ifdef HAVE_LDAP
+
+/****************************************************************
+ parse the raw extension string into a GP_EXT structure
+****************************************************************/
+
ADS_STATUS ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
const char *extension_raw,
struct GP_EXT *gp_ext)
{
char **ext_list;
- char **ext_strings;
+ char **ext_strings = NULL;
int i;
DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
@@ -129,6 +135,10 @@ parse_error:
return ADS_ERROR(LDAP_NO_MEMORY);
}
+/****************************************************************
+ parse the raw link string into a GP_LINK structure
+****************************************************************/
+
ADS_STATUS ads_parse_gplink(TALLOC_CTX *mem_ctx,
const char *gp_link_raw,
uint32 options,
@@ -204,6 +214,10 @@ parse_error:
return ADS_ERROR(LDAP_NO_MEMORY);
}
+/****************************************************************
+ helper call to get a GP_LINK structure from a linkdn
+****************************************************************/
+
ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *link_dn,
@@ -211,7 +225,7 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", "gPOptions", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link;
uint32 gp_options;
@@ -236,6 +250,7 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
}
+ /* perfectly leggal to have no options */
if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
DEBUG(10,("ads_get_gpo_link: no 'gPOptions' attribute found\n"));
gp_options = 0;
@@ -246,6 +261,10 @@ ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
return ads_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
}
+/****************************************************************
+ helper call to add a gp link
+****************************************************************/
+
ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *link_dn,
@@ -254,11 +273,10 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link, *gp_link_new;
ADS_MODLIST mods;
-
/* although ADS allows to set anything here, we better check here if
* the gpo_dn is sane */
@@ -274,6 +292,7 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_add_gpo_link: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
@@ -284,14 +303,11 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
}
- if (gp_link_new == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ads_msgfree(ads, res);
+ ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
mods = ads_init_mods(mem_ctx);
- if (mods == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(mods);
status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
if (!ADS_ERR_OK(status)) {
@@ -301,6 +317,10 @@ ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
return ads_gen_mod(ads, link_dn, mods);
}
+/****************************************************************
+ helper call to delete add a gp link
+****************************************************************/
+
/* untested & broken */
ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
@@ -309,7 +329,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
{
ADS_STATUS status;
const char *attrs[] = {"gPLink", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *gp_link, *gp_link_new = NULL;
ADS_MODLIST mods;
@@ -332,6 +352,7 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_delete_gpo_link: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
@@ -341,16 +362,13 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
}
/* find link to delete */
-// gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
+ /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt); */
- if (gp_link_new == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ads_msgfree(ads, res);
+ ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
mods = ads_init_mods(mem_ctx);
- if (mods == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(mods);
status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
if (!ADS_ERR_OK(status)) {
@@ -360,70 +378,57 @@ ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
return ads_gen_mod(ads, link_dn, mods);
}
-ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *res,
- const char *gpo_dn,
- struct GROUP_POLICY_OBJECT *gpo)
+/****************************************************************
+ parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
+****************************************************************/
+
+ ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *res,
+ const char *gpo_dn,
+ struct GROUP_POLICY_OBJECT *gpo)
{
ZERO_STRUCTP(gpo);
- if (res == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(res);
if (gpo_dn) {
gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
} else {
gpo->ds_path = ads_get_dn(ads, res);
}
- if (gpo->ds_path == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
- ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
- /* split here for convenience */
- gpo->version_user = gpo->version >> 16;
- gpo->version_machine = gpo->version & 0xffff;
-
/* sure ??? */
if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
- ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res, "gPCFileSysPath");
- if (gpo->file_sys_path == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->file_sys_path);
gpo->display_name = ads_pull_string(ads, mem_ctx, res, "displayName");
- if (gpo->display_name == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
gpo->name = ads_pull_string(ads, mem_ctx, res, "name");
- if (gpo->name == NULL) {
- ads_msgfree(ads, res);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
/* ???, this is optional to have and what does it depend on, the 'flags' ?) */
gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res, "gPCMachineExtensionNames");
gpo->user_extensions = ads_pull_string(ads, mem_ctx, res, "gPCUserExtensionNames");
- ads_msgfree(ads, res);
-
return ADS_ERROR(LDAP_SUCCESS);
}
+/****************************************************************
+ get a GROUP_POLICY_OBJECT structure based on different input paramters
+****************************************************************/
+
ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *gpo_dn,
@@ -432,7 +437,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
struct GROUP_POLICY_OBJECT *gpo)
{
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *dn;
const char *filter;
const char *attrs[] = { "cn", "displayName", "flags", "gPCFileSysPath",
@@ -460,9 +465,7 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
"(&(objectclass=groupPolicyContainer)(%s=%s))",
display_name ? "displayName" : "name",
display_name ? display_name : guid_name);
- if (filter == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(filter);
status = ads_do_search_all(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE, filter,
@@ -476,21 +479,27 @@ ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
if (ads_count_replies(ads, res) != 1) {
DEBUG(10,("ads_get_gpo: no result\n"));
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
-
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
return status;
}
+/****************************************************************
+ add a gplink to the GROUP_POLICY_OBJECT linked list
+****************************************************************/
+
ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
struct GROUP_POLICY_OBJECT **gpo_list,
@@ -522,9 +531,7 @@ ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
}
new_gpo = TALLOC_P(mem_ctx, struct GROUP_POLICY_OBJECT);
- if (new_gpo == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
ZERO_STRUCTP(new_gpo);
@@ -545,6 +552,10 @@ ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+/****************************************************************
+ get the full list of GROUP_POLICY_OBJECTs for a given dn
+****************************************************************/
+
ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
const char *dn,
@@ -678,3 +689,5 @@ ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+
+#endif /* HAVE_LDAP */
diff --git a/source/libgpo/gpo_parse.c b/source/libgpo/gpo_parse.c
new file mode 100644
index 00000000000..ec272bf238b
--- /dev/null
+++ b/source/libgpo/gpo_parse.c
@@ -0,0 +1,299 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Group Policy Object Support
+ * Copyright (C) Guenther Deschner 2005-2006
+ *
+ * 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 "iniparser/src/iniparser.h"
+
+/****************************************************************
+ parse the local gpt.ini file
+****************************************************************/
+
+#define GPT_INI_SECTION_GENERAL "General"
+#define GPT_INI_PARAMETER_VERSION "Version"
+#define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
+
+NTSTATUS parse_gpt_ini(TALLOC_CTX *mem_ctx, const char *filename, uint32 *version, char **display_name)
+{
+ NTSTATUS result;
+ uint32 v;
+ char *name = NULL;
+ dictionary *d;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if ((name = iniparser_getstring(d, GPT_INI_SECTION_GENERAL
+ ":"GPT_INI_PARAMETER_DISPLAYNAME, NULL)) == NULL) {
+ /* the default domain policy and the default domain controller
+ * policy never have a displayname in their gpt.ini file */
+ DEBUG(10,("parse_gpt_ini: no name in %s\n", filename));
+ }
+
+ if (name && display_name) {
+ *display_name = talloc_strdup(mem_ctx, name);
+ if (*display_name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+ }
+
+ if ((v = iniparser_getint(d, GPT_INI_SECTION_GENERAL
+ ":"GPT_INI_PARAMETER_VERSION, Undefined)) == Undefined) {
+ DEBUG(10,("parse_gpt_ini: no version\n"));
+ result = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto out;
+ }
+
+ if (version) {
+ *version = v;
+ }
+
+ result = NT_STATUS_OK;
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return result;
+}
+
+#if 0 /* not yet */
+
+/****************************************************************
+ parse the Version section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_VERSION "Version"
+#define GPTTMPL_PARAMETER_REVISION "Revision"
+#define GPTTMPL_PARAMETER_SIGNATURE "signature"
+#define GPTTMPL_CHICAGO "$CHICAGO$" /* whatever this is good for... */
+#define GPTTMPL_SECTION_UNICODE "Unicode"
+#define GPTTMPL_PARAMETER_UNICODE "Unicode"
+
+static NTSTATUS parse_gpttmpl(dictionary *d, uint32 *version_out)
+{
+ const char *signature = NULL;
+ uint32 version;
+
+ if ((signature = iniparser_getstring(d, GPTTMPL_SECTION_VERSION
+ ":"GPTTMPL_PARAMETER_SIGNATURE, NULL)) == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (!strequal(signature, GPTTMPL_CHICAGO)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if ((version = iniparser_getint(d, GPTTMPL_SECTION_VERSION
+ ":"GPTTMPL_PARAMETER_REVISION, Undefined)) == Undefined) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (version_out) {
+ *version_out = version;
+ }
+
+ /* treat that as boolean */
+ if ((!iniparser_getboolean(d, GPTTMPL_SECTION_UNICODE
+ ":"GPTTMPL_PARAMETER_UNICODE, Undefined)) == Undefined) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+ parse the "System Access" section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_SYSTEM_ACCESS "System Access"
+#define GPTTMPL_PARAMETER_MINPWDAGE "MinimumPasswordAge"
+#define GPTTMPL_PARAMETER_MAXPWDAGE "MaximumPasswordAge"
+#define GPTTMPL_PARAMETER_MINPWDLEN "MinimumPasswordLength"
+#define GPTTMPL_PARAMETER_PWDCOMPLEX "PasswordComplexity"
+#define GPTTMPL_PARAMETER_PWDHISTORY "PasswordHistorySize"
+#define GPTTMPL_PARAMETER_LOCKOUTCOUNT "LockoutBadCount"
+
+static NTSTATUS parse_gpttmpl_system_access(const char *filename)
+{
+ NTSTATUS status;
+ dictionary *d = NULL;
+ uint32 pwd_min_age, pwd_max_age, pwd_min_len, pwd_history;
+ uint32 lockout_count;
+ BOOL pwd_complex;
+ uint32 version;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ status = parse_gpttmpl(d, &version);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = NT_STATUS_INVALID_PARAMETER;
+
+ if ((pwd_min_age = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDAGE, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_max_age = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDAGE, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_min_len = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_MINPWDLEN, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_complex = iniparser_getboolean(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_PWDCOMPLEX, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((pwd_history = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_PWDHISTORY, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ if ((lockout_count = iniparser_getint(d, GPTTMPL_SECTION_SYSTEM_ACCESS
+ ":"GPTTMPL_PARAMETER_LOCKOUTCOUNT, Undefined)) == Undefined) {
+ goto out;
+ }
+
+ /* TODO ?
+ RequireLogonToChangePassword = 0
+ ForceLogoffWhenHourExpire = 0
+ ClearTextPassword = 0
+ */
+
+ status = NT_STATUS_OK;
+
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return status;
+}
+
+/****************************************************************
+ parse the "Kerberos Policy" section from gpttmpl file
+****************************************************************/
+
+#define GPTTMPL_SECTION_KERBEROS_POLICY "Kerberos Policy"
+#define GPTTMPL_PARAMETER_MAXTKTAGE "MaxTicketAge"
+#define GPTTMPL_PARAMETER_MAXRENEWAGE "MaxRenewAge"
+#define GPTTMPL_PARAMETER_MAXTGSAGE "MaxServiceAge"
+#define GPTTMPL_PARAMETER_MAXCLOCKSKEW "MaxClockSkew"
+#define GPTTMPL_PARAMETER_TKTVALIDATECLIENT "TicketValidateClient"
+
+static NTSTATUS parse_gpttmpl_kerberos_policy(const char *filename)
+{
+ NTSTATUS status;
+ dictionary *d = NULL;
+ uint32 tkt_max_age, tkt_max_renew, tgs_max_age, max_clock_skew;
+ BOOL tkt_validate;
+ uint32 version;
+
+ d = iniparser_load(filename);
+ if (d == NULL) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ status = parse_gpttmpl(d, &version);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = NT_STATUS_INVALID_PARAMETER;
+
+ if ((tkt_max_age = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXTKTAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tkt_max_renew = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXRENEWAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tgs_max_age = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXTGSAGE, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((max_clock_skew = iniparser_getint(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_MAXCLOCKSKEW, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ if ((tkt_validate = iniparser_getboolean(d, GPTTMPL_SECTION_KERBEROS_POLICY
+ ":"GPTTMPL_PARAMETER_TKTVALIDATECLIENT, Undefined)) != Undefined) {
+ goto out;
+ }
+
+ status = NT_STATUS_OK;
+
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ return status;
+}
+
+#endif
+
+/*
+
+perfectly parseable with iniparser:
+
+{GUID}/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf
+
+
+[Unicode]
+Unicode=yes
+[System Access]
+MinimumPasswordAge = 1
+MaximumPasswordAge = 42
+MinimumPasswordLength = 7
+PasswordComplexity = 1
+PasswordHistorySize = 24
+LockoutBadCount = 0
+RequireLogonToChangePassword = 0
+ForceLogoffWhenHourExpire = 0
+ClearTextPassword = 0
+[Kerberos Policy]
+MaxTicketAge = 10
+MaxRenewAge = 7
+MaxServiceAge = 600
+MaxClockSkew = 5
+TicketValidateClient = 1
+[Version]
+signature="$CHICAGO$"
+Revision=1
+*/
diff --git a/source/libads/gpo_util.c b/source/libgpo/gpo_util.c
index 8f913c19714..9c74fc6a73a 100644
--- a/source/libads/gpo_util.c
+++ b/source/libgpo/gpo_util.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* Group Policy Object Support
- * Copyright (C) Guenther Deschner 2005
+ * Copyright (C) Guenther Deschner 2005-2006
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,10 +20,12 @@
#include "includes.h"
+#ifdef HAVE_LDAP
+
#define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
#define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
-/* should we store a parsed guid ? UUID_FLAT guid; */
+/* should we store a parsed guid ? */
struct gpo_table {
const char *name;
const char *guid_string;
@@ -35,6 +37,7 @@ struct snapin_table {
ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
};
+#if 0 /* unused */
static struct gpo_table gpo_default_policy[] = {
{ DEFAULT_DOMAIN_POLICY,
"31B2F340-016D-11D2-945F-00C04FB984F9" },
@@ -42,7 +45,7 @@ static struct gpo_table gpo_default_policy[] = {
"6AC1786C-016F-11D2-945F-00C04fB984F9" },
{ NULL, NULL }
};
-
+#endif
/* the following is seen in gPCMachineExtensionNames or gPCUserExtensionNames */
@@ -125,6 +128,19 @@ static const char *guid_string_to_name(const char *guid_string, struct gpo_table
return NULL;
}
+static const char *snapin_guid_string_to_name(const char *guid_string,
+ struct snapin_table *table)
+{
+ int i;
+ for (i = 0; table[i].guid_string; i++) {
+ if (strequal(guid_string, table[i].guid_string)) {
+ return table[i].name;
+ }
+ }
+ return NULL;
+}
+
+#if 0 /* unused */
static const char *default_gpo_name_to_guid_string(const char *name)
{
return name_to_guid_string(name, gpo_default_policy);
@@ -134,6 +150,7 @@ static const char *default_gpo_guid_string_to_name(const char *guid)
{
return guid_string_to_name(guid, gpo_default_policy);
}
+#endif
const char *cse_gpo_guid_string_to_name(const char *guid)
{
@@ -147,34 +164,34 @@ static const char *cse_gpo_name_to_guid_string(const char *name)
const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
{
- return guid_string_to_name(guid, gpo_cse_snapin_extensions);
+ return snapin_guid_string_to_name(guid, gpo_cse_snapin_extensions);
}
-void dump_gp_ext(struct GP_EXT *gp_ext)
+void dump_gp_ext(struct GP_EXT *gp_ext, int debuglevel)
{
- int lvl = 10;
+ int lvl = debuglevel;
int i;
if (gp_ext == NULL) {
return;
}
- DEBUG(lvl,("---------------------\n\n"));
- DEBUGADD(lvl,("name:\t\t\t%s\n", gp_ext->gp_extension));
+ DEBUG(lvl,("\t---------------------\n\n"));
+ DEBUGADD(lvl,("\tname:\t\t\t%s\n", gp_ext->gp_extension));
for (i=0; i< gp_ext->num_exts; i++) {
- DEBUGADD(lvl,("extension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
- DEBUGADD(lvl,("extension (name):\t\t\t%s\n", gp_ext->extensions[i]));
+ DEBUGADD(lvl,("\textension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
+ DEBUGADD(lvl,("\textension (name):\t\t\t%s\n", gp_ext->extensions[i]));
- DEBUGADD(lvl,("snapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
- DEBUGADD(lvl,("snapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
+ DEBUGADD(lvl,("\tsnapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
+ DEBUGADD(lvl,("\tsnapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
}
}
-void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
+void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo, int debuglevel)
{
- int lvl = 1;
+ int lvl = debuglevel;
if (gpo == NULL) {
return;
@@ -185,8 +202,10 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
DEBUGADD(lvl,("name:\t\t\t%s\n", gpo->name));
DEBUGADD(lvl,("displayname:\t\t%s\n", gpo->display_name));
DEBUGADD(lvl,("version:\t\t%d (0x%08x)\n", gpo->version, gpo->version));
- DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", gpo->version_user, gpo->version_user));
- DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", gpo->version_machine, gpo->version_machine));
+ DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_USER(gpo->version)));
+ DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", GPO_VERSION_MACHINE(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version)));
DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
@@ -232,7 +251,7 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
if (!ADS_ERR_OK(status)) {
return;
}
- dump_gp_ext(&gp_ext);
+ dump_gp_ext(&gp_ext, lvl);
}
if (gpo->user_extensions) {
@@ -246,9 +265,9 @@ void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
if (!ADS_ERR_OK(status)) {
return;
}
- dump_gp_ext(&gp_ext);
+ dump_gp_ext(&gp_ext, lvl);
}
-};
+}
void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
{
@@ -302,7 +321,7 @@ void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
return;
}
- dump_gpo(mem_ctx, &gpo);
+ dump_gpo(mem_ctx, &gpo, lvl);
}
}
}
@@ -445,11 +464,9 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
struct GROUP_POLICY_OBJECT *gpo_list;
const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
char *filter, *dn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
uint32 uac;
- return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
-
filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
if (filter == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
@@ -464,27 +481,37 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
}
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ ads_msgfree(ads, res);
+ ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
+ ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
if (!ADS_ERR_OK(status)) {
+ ads_memfree(ads, dn);
return status;
}
+ ads_memfree(ads, dn);
+
status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list,
cse_gpo_name_to_guid_string("Security"),
GPO_LIST_FLAG_MACHINE);
@@ -494,3 +521,128 @@ ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
return ADS_ERROR(LDAP_SUCCESS);
}
+
+/****************************************************************
+ check wether the version number in a GROUP_POLICY_OBJECT match those of the
+ locally stored version. If not, fetch the required policy via CIFS
+****************************************************************/
+
+NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT *gpo,
+ struct cli_state **cli_out)
+{
+ NTSTATUS result;
+ char *server, *share, *nt_path, *unix_path;
+ uint32 sysvol_gpt_version = 0;
+ char *display_name;
+ struct cli_state *cli = NULL;
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &share, &nt_path, &unix_path);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
+ unix_path,
+ &sysvol_gpt_version,
+ &display_name);
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_FILE)) {
+ DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
+ nt_errstr(result)));
+ goto out;
+ }
+
+ while (gpo->version > sysvol_gpt_version) {
+
+ DEBUG(1,("check_refresh_gpo: need to refresh GPO\n"));
+
+ if (*cli_out == NULL) {
+
+ result = cli_full_connection(&cli, global_myname(),
+ server, /* ads->config.ldap_server_name, */
+ NULL, 0,
+ share, "A:",
+ ads->auth.user_name, NULL, ads->auth.password,
+ CLI_FULL_CONNECTION_USE_KERBEROS,
+ Undefined, NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("check_refresh_gpo: failed to connect: %s\n", nt_errstr(result)));
+ goto out;
+ }
+
+ *cli_out = cli;
+ }
+
+ result = ads_fetch_gpo_files(ads, mem_ctx, *cli_out, gpo);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+
+ result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
+ unix_path,
+ &sysvol_gpt_version,
+ &display_name);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
+ nt_errstr(result)));
+ goto out;
+ }
+
+ if (gpo->version == sysvol_gpt_version) {
+ break;
+ }
+ }
+
+ DEBUG(10,("Name:\t\t\t%s\n", gpo->display_name));
+ DEBUGADD(10,("sysvol GPT version:\t%d (user: %d, machine: %d)\n",
+ sysvol_gpt_version,
+ GPO_VERSION_USER(sysvol_gpt_version),
+ GPO_VERSION_MACHINE(sysvol_gpt_version)));
+ DEBUGADD(10,("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
+ gpo->version,
+ GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version)));
+
+ result = NT_STATUS_OK;
+
+ out:
+ return result;
+
+}
+
+/****************************************************************
+ check wether the version numbers in the gpo_list match the locally stored, if
+ not, go and get each required GPO via CIFS
+ ****************************************************************/
+
+NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT *gpo_list)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct cli_state *cli = NULL;
+ struct GROUP_POLICY_OBJECT *gpo;
+
+ for (gpo = gpo_list; gpo; gpo = gpo->next) {
+
+ result = check_refresh_gpo(ads, mem_ctx, gpo, &cli);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
+ }
+
+ result = NT_STATUS_OK;
+
+ out:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return result;
+}
+
+#endif /* HAVE_LDAP */
diff --git a/source/libmsrpc/cac_lsarpc.c b/source/libmsrpc/cac_lsarpc.c
index 72f22de5f22..6b8987d71d8 100644
--- a/source/libmsrpc/cac_lsarpc.c
+++ b/source/libmsrpc/cac_lsarpc.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation (LSA pipe)
@@ -21,1061 +22,1212 @@
#include "libmsrpc.h"
#include "libsmb_internal.h"
-int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenPolicy *op) {
- SMBCSRV *srv = NULL;
- POLICY_HND *policy = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!mem_ctx || !op) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- op->out.pol = NULL;
-
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
-
- /*see if there is already an active session on this pipe, if not then open one*/
- if(!hnd->_internal.pipes[PI_LSARPC]) {
- pipe_hnd = cli_rpc_pipe_open_noauth(&(srv->cli), PI_LSARPC, &(hnd->status));
-
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_UNSUCCESSFUL;
- return CAC_FAILURE;
- }
-
- hnd->_internal.pipes[PI_LSARPC] = True;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- policy = TALLOC_P(mem_ctx, POLICY_HND);
- if(!policy) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- /*need to make sure that our nt status is good otherwise check might fail below*/
- hnd->status = NT_STATUS_OK;
-
- if(hnd->_internal.srv_level >= SRV_WIN_2K) {
-
- /*try using open_policy2, if this fails try again in next block using open_policy, if that works then adjust hnd->_internal.srv_level*/
-
- /*we shouldn't need to modify the access mask to make it work here*/
- hnd->status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
-
- }
-
- if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) {
- hnd->status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
-
- if(hnd->_internal.srv_level > SRV_WIN_NT4 && NT_STATUS_IS_OK(hnd->status)) {
- /*change the server level to 1*/
- hnd->_internal.srv_level = SRV_WIN_NT4;
- }
-
- }
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- op->out.pol = policy;
-
- return CAC_SUCCESS;
+int cac_LsaOpenPolicy( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaOpenPolicy *op )
+{
+ SMBCSRV *srv = NULL;
+ POLICY_HND *policy = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !mem_ctx || !op ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ op->out.pol = NULL;
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ /*see if there is already an active session on this pipe, if not then open one */
+ if ( !hnd->_internal.pipes[PI_LSARPC] ) {
+ pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_LSARPC,
+ &hnd->status );
+
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_UNSUCCESSFUL;
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_LSARPC] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ policy = TALLOC_P( mem_ctx, POLICY_HND );
+ if ( !policy ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ /*need to make sure that our nt status is good otherwise check might fail below */
+ hnd->status = NT_STATUS_OK;
+
+ if ( hnd->_internal.srv_level >= SRV_WIN_2K ) {
+
+ /*try using open_policy2, if this fails try again in next block using open_policy, if that works then adjust hnd->_internal.srv_level */
+
+ /*we shouldn't need to modify the access mask to make it work here */
+ hnd->status =
+ rpccli_lsa_open_policy2( pipe_hnd, mem_ctx,
+ op->in.security_qos,
+ op->in.access, policy );
+
+ }
+
+ if ( hnd->_internal.srv_level < SRV_WIN_2K
+ || !NT_STATUS_IS_OK( hnd->status ) ) {
+ hnd->status =
+ rpccli_lsa_open_policy( pipe_hnd, mem_ctx,
+ op->in.security_qos,
+ op->in.access, policy );
+
+ if ( hnd->_internal.srv_level > SRV_WIN_NT4
+ && NT_STATUS_IS_OK( hnd->status ) ) {
+ /*change the server level to 1 */
+ hnd->_internal.srv_level = SRV_WIN_NT4;
+ }
+
+ }
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.pol = policy;
+
+ return CAC_SUCCESS;
}
-int cac_LsaClosePolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *pol) {
+int cac_LsaClosePolicy( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * pol )
+{
+
+ struct rpc_pipe_client *pipe_hnd = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd)
- return CAC_FAILURE;
-
- if(!pol)
- return CAC_SUCCESS; /*if the policy handle doesnt exist then it's already closed*/
+ if ( !pol )
+ return CAC_SUCCESS; /*if the policy handle doesnt exist then it's already closed */
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_lsa_close(pipe_hnd, mem_ctx, pol);
+ hnd->status = rpccli_lsa_close( pipe_hnd, mem_ctx, pol );
- TALLOC_FREE(pol);
+ TALLOC_FREE( pol );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_LsaGetNamesFromSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetNamesFromSids *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- int result = -1;
-
- int i;
-
- /*buffers for outputs*/
- char **domains = NULL;
- char **names = NULL;
- uint32 *types = NULL;
-
- CacSidInfo *sids_out = NULL;
- DOM_SID *unknown_out = NULL;
- int num_unknown = 0;
-
- int num_sids;
-
- int found_idx;
- int unknown_idx;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!mem_ctx || !op || !op->in.pol || !op->in.sids) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- num_sids = op->in.num_sids;
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
-
-
- /*now actually lookup the names*/
- hnd->status = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, op->in.pol, op->in.num_sids,
- op->in.sids, &domains, &names, &types);
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- /*this is the easy part, just make the out.sids array*/
- sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_sids);
- if(!sids_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_sids; i++) {
- sids_out[i].sid = op->in.sids[i];
- sids_out[i].name = names[i];
- sids_out[i].domain = domains[i];
- }
-
- result = CAC_SUCCESS;
- }
- else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
- /*first find out how many couldn't be looked up*/
-
- for(i = 0; i < num_sids; i++) {
- if(names[i] == NULL) {
- num_unknown++;
- }
- }
-
- if( num_unknown >= num_sids) {
- hnd->status = NT_STATUS_UNSUCCESSFUL;
- return CAC_FAILURE;
- }
-
- sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_sids - num_unknown));
- if(!sids_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- unknown_out = TALLOC_ARRAY(mem_ctx, DOM_SID, num_unknown);
- if(!unknown_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- found_idx = unknown_idx = 0;
-
- /*now we can actually do the real work*/
- for(i = 0; i < num_sids; i++) {
- if(names[i] != NULL) {
- sids_out[found_idx].sid = op->in.sids[i];
- sids_out[found_idx].name = names[i];
- sids_out[found_idx].domain = domains[i];
-
- found_idx++;
- }
- else { /*then this one didnt work out*/
- unknown_out[unknown_idx] = op->in.sids[i];
-
- unknown_idx++;
- }
- }
-
- result = CAC_PARTIAL_SUCCESS;
- }
- else { /*then it failed for some reason*/
- return CAC_FAILURE;
- }
-
- op->out.num_found = num_sids - num_unknown;
- op->out.sids = sids_out;
- op->out.unknown = unknown_out;
-
- return result;
-
+int cac_LsaGetNamesFromSids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaGetNamesFromSids *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ int result = -1;
+
+ int i;
+
+ /*buffers for outputs */
+ char **domains = NULL;
+ char **names = NULL;
+ enum lsa_SidType *types = NULL;
+
+ CacSidInfo *sids_out = NULL;
+ DOM_SID *unknown_out = NULL;
+ int num_unknown = 0;
+
+ int num_sids;
+
+ int found_idx;
+ int unknown_idx;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !mem_ctx || !op || !op->in.pol || !op->in.sids ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ num_sids = op->in.num_sids;
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+
+
+ /*now actually lookup the names */
+ hnd->status =
+ rpccli_lsa_lookup_sids( pipe_hnd, mem_ctx, op->in.pol,
+ op->in.num_sids, op->in.sids,
+ &domains, &names, &types );
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ /*this is the easy part, just make the out.sids array */
+ sids_out = TALLOC_ARRAY( mem_ctx, CacSidInfo, num_sids );
+ if ( !sids_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_sids; i++ ) {
+ sids_out[i].sid = op->in.sids[i];
+ sids_out[i].name = names[i];
+ sids_out[i].domain = domains[i];
+ }
+
+ result = CAC_SUCCESS;
+ } else if ( NT_STATUS_V( hnd->status ) ==
+ NT_STATUS_V( STATUS_SOME_UNMAPPED ) ) {
+ /*first find out how many couldn't be looked up */
+
+ for ( i = 0; i < num_sids; i++ ) {
+ if ( names[i] == NULL ) {
+ num_unknown++;
+ }
+ }
+
+ if ( num_unknown >= num_sids ) {
+ hnd->status = NT_STATUS_UNSUCCESSFUL;
+ return CAC_FAILURE;
+ }
+
+ sids_out =
+ TALLOC_ARRAY( mem_ctx, CacSidInfo,
+ ( num_sids - num_unknown ) );
+ if ( !sids_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ unknown_out = TALLOC_ARRAY( mem_ctx, DOM_SID, num_unknown );
+ if ( !unknown_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ found_idx = unknown_idx = 0;
+
+ /*now we can actually do the real work */
+ for ( i = 0; i < num_sids; i++ ) {
+ if ( names[i] != NULL ) {
+ sids_out[found_idx].sid = op->in.sids[i];
+ sids_out[found_idx].name = names[i];
+ sids_out[found_idx].domain = domains[i];
+
+ found_idx++;
+ } else { /*then this one didnt work out */
+ unknown_out[unknown_idx] = op->in.sids[i];
+
+ unknown_idx++;
+ }
+ }
+
+ result = CAC_PARTIAL_SUCCESS;
+ } else { /*then it failed for some reason */
+ return CAC_FAILURE;
+ }
+
+ op->out.num_found = num_sids - num_unknown;
+ op->out.sids = sids_out;
+ op->out.unknown = unknown_out;
+
+ return result;
+
}
-int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSidsFromNames *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- int result = -1;
-
- int i;
-
- /*buffers for outputs*/
- DOM_SID *sids = NULL;
- uint32 *types = NULL;
-
- CacSidInfo *sids_out = NULL;
- char **unknown_out = NULL;
- int num_unknown = 0;
-
- int num_names;
-
- int found_idx = 0;
- int unknown_idx = 0;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!mem_ctx || !op || !op->in.pol || !op->in.names) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- num_names = op->in.num_names;
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
-
- /*now actually lookup the names*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, num_names,
- (const char **)op->in.names, NULL, &sids, &types);
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- /*this is the easy part, just make the out.sids array*/
- sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_names);
- if(!sids_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_names; i++) {
- sids_out[i].sid = sids[i];
- sids_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]);
- sids_out[i].domain = NULL;
- }
-
- result = CAC_SUCCESS;
- }
- else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
- /*first find out how many couldn't be looked up*/
-
- for(i = 0; i < num_names; i++) {
- if(types[i] == SID_NAME_UNKNOWN) {
- num_unknown++;
- }
- }
-
- if( num_unknown >= num_names) {
- hnd->status = NT_STATUS_UNSUCCESSFUL;
- return CAC_FAILURE;
- }
-
- sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_names - num_unknown));
- if(!sids_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- unknown_out = TALLOC_ARRAY(mem_ctx, char *, num_unknown);
- if(!unknown_out) {
- errno = ENOMEM;
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- unknown_idx = found_idx = 0;
-
- /*now we can actually do the real work*/
- for(i = 0; i < num_names; i++) {
- if(types[i] != SID_NAME_UNKNOWN) {
- sids_out[found_idx].sid = sids[i];
- sids_out[found_idx].name = talloc_strdup(mem_ctx, op->in.names[i]);
- sids_out[found_idx].domain = NULL;
-
- found_idx++;
- }
- else { /*then this one didnt work out*/
- unknown_out[unknown_idx] = talloc_strdup(mem_ctx, op->in.names[i]);
-
- unknown_idx++;
- }
- }
-
- result = CAC_PARTIAL_SUCCESS;
- }
- else { /*then it failed for some reason*/
- return CAC_FAILURE;
- }
-
- op->out.num_found = num_names - num_unknown;
- op->out.sids = sids_out;
- op->out.unknown = unknown_out;
-
- return result;
-
+int cac_LsaGetSidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaGetSidsFromNames *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ int result = -1;
+
+ int i;
+
+ /*buffers for outputs */
+ DOM_SID *sids = NULL;
+ enum lsa_SidType *types = NULL;
+
+ CacSidInfo *sids_out = NULL;
+ char **unknown_out = NULL;
+ int num_unknown = 0;
+
+ int num_names;
+
+ int found_idx = 0;
+ int unknown_idx = 0;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !mem_ctx || !op || !op->in.pol || !op->in.names ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ num_names = op->in.num_names;
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+
+ /*now actually lookup the names */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol,
+ num_names,
+ ( const char ** ) op->in.names, NULL,
+ &sids, &types );
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ /*this is the easy part, just make the out.sids array */
+ sids_out = TALLOC_ARRAY( mem_ctx, CacSidInfo, num_names );
+ if ( !sids_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_names; i++ ) {
+ sids_out[i].sid = sids[i];
+ sids_out[i].name =
+ talloc_strdup( mem_ctx, op->in.names[i] );
+ sids_out[i].domain = NULL;
+ }
+
+ result = CAC_SUCCESS;
+ } else if ( NT_STATUS_V( hnd->status ) ==
+ NT_STATUS_V( STATUS_SOME_UNMAPPED ) ) {
+ /*first find out how many couldn't be looked up */
+
+ for ( i = 0; i < num_names; i++ ) {
+ if ( types[i] == SID_NAME_UNKNOWN ) {
+ num_unknown++;
+ }
+ }
+
+ if ( num_unknown >= num_names ) {
+ hnd->status = NT_STATUS_UNSUCCESSFUL;
+ return CAC_FAILURE;
+ }
+
+ sids_out =
+ TALLOC_ARRAY( mem_ctx, CacSidInfo,
+ ( num_names - num_unknown ) );
+ if ( !sids_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ unknown_out = TALLOC_ARRAY( mem_ctx, char *, num_unknown );
+ if ( !unknown_out ) {
+ errno = ENOMEM;
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ unknown_idx = found_idx = 0;
+
+ /*now we can actually do the real work */
+ for ( i = 0; i < num_names; i++ ) {
+ if ( types[i] != SID_NAME_UNKNOWN ) {
+ sids_out[found_idx].sid = sids[i];
+ sids_out[found_idx].name =
+ talloc_strdup( mem_ctx,
+ op->in.names[i] );
+ sids_out[found_idx].domain = NULL;
+
+ found_idx++;
+ } else { /*then this one didnt work out */
+ unknown_out[unknown_idx] =
+ talloc_strdup( mem_ctx,
+ op->in.names[i] );
+
+ unknown_idx++;
+ }
+ }
+
+ result = CAC_PARTIAL_SUCCESS;
+ } else { /*then it failed for some reason */
+ return CAC_FAILURE;
+ }
+
+ op->out.num_found = num_names - num_unknown;
+ op->out.sids = sids_out;
+ op->out.unknown = unknown_out;
+
+ return result;
+
}
-int cac_LsaFetchSid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaFetchSid *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- int result = -1;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!mem_ctx || !op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- op->out.local_sid = NULL;
- op->out.domain_sid = NULL;
-
- if( (op->in.info_class & CAC_LOCAL_INFO) == CAC_LOCAL_INFO) {
- DOM_SID *local_sid = NULL;
- char *dom_name = NULL;
-
- hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_LOCAL_INFO, &dom_name, &local_sid);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- result = CAC_FAILURE;
- goto domain;
- }
-
- op->out.local_sid = talloc(mem_ctx, CacSidInfo);
- if(!op->out.local_sid) {
- hnd->status = NT_STATUS_NO_MEMORY;
- result = CAC_FAILURE;
- goto domain;
- }
-
- op->out.local_sid->domain = dom_name;
-
- sid_copy(&op->out.local_sid->sid, local_sid);
- TALLOC_FREE(local_sid);
- }
-
-domain:
-
- if( (op->in.info_class & CAC_DOMAIN_INFO) == CAC_DOMAIN_INFO) {
- DOM_SID *domain_sid;
- char *dom_name;
-
- hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_DOMAIN_INFO, &dom_name, &domain_sid);
- if(!NT_STATUS_IS_OK(hnd->status)) {
- /*if we succeeded above, report partial success*/
- result = CAC_FAILURE;
- goto done;
- }
- else if(result == CAC_FAILURE) {
- /*if we failed above but succeded here then report partial success*/
- result = CAC_PARTIAL_SUCCESS;
- }
-
- op->out.domain_sid = talloc(mem_ctx, CacSidInfo);
- if(!op->out.domain_sid) {
- hnd->status = NT_STATUS_NO_MEMORY;
- result = CAC_FAILURE;
- goto done;
- }
-
- op->out.domain_sid->domain = dom_name;
- sid_copy(&op->out.domain_sid->sid, domain_sid);
- TALLOC_FREE(domain_sid);
- }
-
-done:
- return result;
+int cac_LsaFetchSid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaFetchSid *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ int result = -1;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !mem_ctx || !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ op->out.local_sid = NULL;
+ op->out.domain_sid = NULL;
+
+ if ( ( op->in.info_class & CAC_LOCAL_INFO ) == CAC_LOCAL_INFO ) {
+ DOM_SID *local_sid = NULL;
+ char *dom_name = NULL;
+
+ hnd->status =
+ rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx,
+ op->in.pol,
+ CAC_LOCAL_INFO,
+ &dom_name, &local_sid );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ result = CAC_FAILURE;
+ goto domain;
+ }
+
+ op->out.local_sid = talloc( mem_ctx, CacSidInfo );
+ if ( !op->out.local_sid ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ result = CAC_FAILURE;
+ goto domain;
+ }
+
+ op->out.local_sid->domain = dom_name;
+
+ sid_copy( &op->out.local_sid->sid, local_sid );
+ TALLOC_FREE( local_sid );
+ }
+
+ domain:
+
+ if ( ( op->in.info_class & CAC_DOMAIN_INFO ) == CAC_DOMAIN_INFO ) {
+ DOM_SID *domain_sid;
+ char *dom_name;
+
+ hnd->status =
+ rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx,
+ op->in.pol,
+ CAC_DOMAIN_INFO,
+ &dom_name,
+ &domain_sid );
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ /*if we succeeded above, report partial success */
+ result = CAC_FAILURE;
+ goto done;
+ } else if ( result == CAC_FAILURE ) {
+ /*if we failed above but succeded here then report partial success */
+ result = CAC_PARTIAL_SUCCESS;
+ }
+
+ op->out.domain_sid = talloc( mem_ctx, CacSidInfo );
+ if ( !op->out.domain_sid ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ result = CAC_FAILURE;
+ goto done;
+ }
+
+ op->out.domain_sid->domain = dom_name;
+ sid_copy( &op->out.domain_sid->sid, domain_sid );
+ TALLOC_FREE( domain_sid );
+ }
+
+ done:
+ return result;
}
-int cac_LsaQueryInfoPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryInfoPolicy *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- char *domain_name = NULL;
- char *dns_name = NULL;
- char *forest_name = NULL;
- struct uuid *domain_guid = NULL;
- DOM_SID *domain_sid = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*only works if info_class parm is 12*/
- hnd->status = rpccli_lsa_query_info_policy2(pipe_hnd, mem_ctx, op->in.pol, 12,
- &domain_name, &dns_name, &forest_name, &domain_guid, &domain_sid);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- op->out.domain_name = domain_name;
- op->out.dns_name = dns_name;
- op->out.forest_name = forest_name;
- op->out.domain_guid = domain_guid;
- op->out.domain_sid = domain_sid;
-
- return CAC_SUCCESS;
+int cac_LsaQueryInfoPolicy( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaQueryInfoPolicy *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ char *domain_name = NULL;
+ char *dns_name = NULL;
+ char *forest_name = NULL;
+ struct GUID *domain_guid = NULL;
+ DOM_SID *domain_sid = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*only works if info_class parm is 12 */
+ hnd->status =
+ rpccli_lsa_query_info_policy2( pipe_hnd, mem_ctx, op->in.pol,
+ 12, &domain_name, &dns_name,
+ &forest_name, &domain_guid,
+ &domain_sid );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.domain_name = domain_name;
+ op->out.dns_name = dns_name;
+ op->out.forest_name = forest_name;
+ op->out.domain_guid = domain_guid;
+ op->out.domain_sid = domain_sid;
+
+ return CAC_SUCCESS;
}
-int cac_LsaEnumSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumSids *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_LsaEnumSids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaEnumSids *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 num_sids;
- DOM_SID *sids;
+ uint32 num_sids;
+ DOM_SID *sids;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_lsa_enum_sids(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_sids, &num_sids, &sids);
+ hnd->status =
+ rpccli_lsa_enum_sids( pipe_hnd, mem_ctx, op->in.pol,
+ &( op->out.resume_idx ),
+ op->in.pref_max_sids, &num_sids,
+ &sids );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- op->out.num_sids = num_sids;
- op->out.sids = sids;
+ op->out.num_sids = num_sids;
+ op->out.sids = sids;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumAccountRights *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_LsaEnumAccountRights( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaEnumAccountRights *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 count = 0;
- char **privs = NULL;
+ uint32 count = 0;
+ char **privs = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op->in.name && !op->in.sid) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.name && !op->in.sid ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(op->in.name && !op->in.sid) {
- DOM_SID *user_sid = NULL;
- uint32 *type;
+ if ( op->in.name && !op->in.sid ) {
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type;
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->in.sid = user_sid;
- }
-
- hnd->status = rpccli_lsa_enum_account_rights( pipe_hnd, mem_ctx, op->in.pol, op->in.sid,
- &count, &privs);
+ op->in.sid = user_sid;
+ }
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ hnd->status =
+ rpccli_lsa_enum_account_rights( pipe_hnd, mem_ctx, op->in.pol,
+ op->in.sid, &count, &privs );
- op->out.num_privs = count;
- op->out.priv_names = privs;
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
-}
+ op->out.num_privs = count;
+ op->out.priv_names = privs;
-int cac_LsaEnumTrustedDomains(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumTrustedDomains *op) {
- struct rpc_pipe_client *pipe_hnd;
-
- uint32 num_domains;
- char **domain_names;
- DOM_SID *domain_sids;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_lsa_enum_trust_dom( pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), &num_domains, &domain_names, &domain_sids);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- op->out.num_domains = num_domains;
- op->out.domain_names = domain_names;
- op->out.domain_sids = domain_sids;
-
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_LsaOpenTrustedDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenTrustedDomain *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- POLICY_HND *dom_pol = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op->in.pol || !op->in.access || !op->in.domain_sid) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- dom_pol = talloc(mem_ctx, POLICY_HND);
- if(!dom_pol) {
- hnd->status = NT_STATUS_NO_MEMORY;
- errno = ENOMEM;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_lsa_open_trusted_domain( pipe_hnd, mem_ctx, op->in.pol, op->in.domain_sid, op->in.access, dom_pol);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- op->out.domain_pol = dom_pol;
-
- return CAC_SUCCESS;
+int cac_LsaEnumTrustedDomains( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaEnumTrustedDomains *op )
+{
+ struct rpc_pipe_client *pipe_hnd;
+
+ uint32 num_domains;
+ char **domain_names;
+ DOM_SID *domain_sids;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_lsa_enum_trust_dom( pipe_hnd, mem_ctx, op->in.pol,
+ &( op->out.resume_idx ),
+ &num_domains, &domain_names,
+ &domain_sids );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.num_domains = num_domains;
+ op->out.domain_names = domain_names;
+ op->out.domain_sids = domain_sids;
+
+ return CAC_SUCCESS;
}
-int cac_LsaQueryTrustedDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryTrustedDomainInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_LsaOpenTrustedDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaOpenTrustedDomain *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- LSA_TRUSTED_DOMAIN_INFO *dom_info;
+ POLICY_HND *dom_pol = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.pol || !op->in.info_class) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.pol || !op->in.access || !op->in.domain_sid ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op->in.domain_sid && !op->in.domain_name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ dom_pol = talloc( mem_ctx, POLICY_HND );
+ if ( !dom_pol ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ errno = ENOMEM;
+ return CAC_FAILURE;
+ }
- if(op->in.domain_sid) {
- hnd->status = rpccli_lsa_query_trusted_domain_info_by_sid( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_sid, &dom_info);
- }
- else if(op->in.domain_name) {
- hnd->status = rpccli_lsa_query_trusted_domain_info_by_name( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_name, &dom_info);
- }
+ hnd->status =
+ rpccli_lsa_open_trusted_domain( pipe_hnd, mem_ctx, op->in.pol,
+ op->in.domain_sid,
+ op->in.access, dom_pol );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- op->out.info = dom_info;
-
- return CAC_SUCCESS;
+ op->out.domain_pol = dom_pol;
+ return CAC_SUCCESS;
}
-int cac_LsaEnumPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumPrivileges *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- uint32 num_privs;
- char **priv_names;
- uint32 *high_bits;
- uint32 *low_bits;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_lsa_enum_privilege(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_privs,
- &num_privs, &priv_names, &high_bits, &low_bits);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+int cac_LsaQueryTrustedDomainInfo( CacServerHandle * hnd,
+ TALLOC_CTX * mem_ctx,
+ struct LsaQueryTrustedDomainInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ LSA_TRUSTED_DOMAIN_INFO *dom_info;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.pol || !op->in.info_class ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.domain_sid && !op->in.domain_name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.domain_sid ) {
+ hnd->status =
+ rpccli_lsa_query_trusted_domain_info_by_sid( pipe_hnd,
+ mem_ctx,
+ op->in.
+ pol,
+ op->in.
+ info_class,
+ op->in.
+ domain_sid,
+ &dom_info );
+ } else if ( op->in.domain_name ) {
+ hnd->status =
+ rpccli_lsa_query_trusted_domain_info_by_name
+ ( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class,
+ op->in.domain_name, &dom_info );
+ }
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.info = dom_info;
+
+ return CAC_SUCCESS;
- op->out.num_privs = num_privs;
- op->out.priv_names = priv_names;
- op->out.high_bits = high_bits;
- op->out.low_bits = low_bits;
-
- return CAC_SUCCESS;
}
-int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenAccount *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- POLICY_HND *user_pol = NULL;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.sid && !op->in.name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*look up the user's SID if we have to*/
- if(op->in.name && !op->in.sid) {
- DOM_SID *user_sid = NULL;
- uint32 *type;
-
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->in.sid = user_sid;
- }
-
- user_pol = talloc(mem_ctx, POLICY_HND);
- if(!user_pol) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_lsa_open_account(pipe_hnd, mem_ctx, op->in.pol, op->in.sid, op->in.access, user_pol);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- TALLOC_FREE(user_pol);
- return CAC_FAILURE;
- }
-
- op->out.user = user_pol;
-
- return CAC_SUCCESS;
+int cac_LsaEnumPrivileges( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaEnumPrivileges *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 num_privs;
+ char **priv_names;
+ uint32 *high_bits;
+ uint32 *low_bits;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_lsa_enum_privilege( pipe_hnd, mem_ctx, op->in.pol,
+ &( op->out.resume_idx ),
+ op->in.pref_max_privs, &num_privs,
+ &priv_names, &high_bits,
+ &low_bits );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.num_privs = num_privs;
+ op->out.priv_names = priv_names;
+ op->out.high_bits = high_bits;
+ op->out.low_bits = low_bits;
+
+ return CAC_SUCCESS;
}
-
-int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- DOM_SID *user_sid = NULL;
- uint32 *type = NULL;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol || !op->in.priv_names) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.sid && !op->in.name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(op->in.name && !op->in.sid) {
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->in.sid = user_sid;
- }
-
- hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+int cac_LsaOpenAccount( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaOpenAccount *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ POLICY_HND *user_pol = NULL;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sid && !op->in.name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*look up the user's SID if we have to */
+ if ( op->in.name && !op->in.sid ) {
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type;
+
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->in.sid = user_sid;
+ }
+
+ user_pol = talloc( mem_ctx, POLICY_HND );
+ if ( !user_pol ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_lsa_open_account( pipe_hnd, mem_ctx, op->in.pol,
+ op->in.sid, op->in.access,
+ user_pol );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ TALLOC_FREE( user_pol );
+ return CAC_FAILURE;
+ }
+
+ op->out.user = user_pol;
+
+ return CAC_SUCCESS;
}
-int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaRemovePrivileges *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- DOM_SID *user_sid = NULL;
- uint32 *type = NULL;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol || !op->in.priv_names) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
- if(!op->in.sid && !op->in.name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(op->in.name && !op->in.sid) {
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->in.sid = user_sid;
- }
-
- hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), False, op->in.num_privs, (const char **)op->in.priv_names);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+int cac_LsaAddPrivileges( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaAddPrivileges *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type = NULL;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol || !op->in.priv_names ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sid && !op->in.name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.name && !op->in.sid ) {
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->in.sid = user_sid;
+ }
+
+ hnd->status =
+ rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol,
+ *( op->in.sid ),
+ op->in.num_privs,
+ ( const char ** ) op->in.
+ priv_names );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaClearPrivileges *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- DOM_SID *user_sid = NULL;
- uint32 *type = NULL;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.sid && !op->in.name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(op->in.name && !op->in.sid) {
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->in.sid = user_sid;
- }
-
- hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+int cac_LsaRemovePrivileges( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaRemovePrivileges *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type = NULL;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol || !op->in.priv_names ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sid && !op->in.name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.name && !op->in.sid ) {
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->in.sid = user_sid;
+ }
+
+ hnd->status =
+ rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx,
+ op->in.pol, *( op->in.sid ),
+ False, op->in.num_privs,
+ ( const char ** ) op->in.
+ priv_names );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- DOM_SID *user_sid = NULL;
- uint32 *type = NULL;
-
- if(!hnd) {
- return CAC_FAILURE;
- }
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.pol || !op->in.priv_names) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.sid && !op->in.name) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- return CAC_FAILURE;
- }
-
- if(op->in.name && !op->in.sid) {
- /*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->in.sid = user_sid;
- }
-
- /*first remove all privileges*/
- hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+int cac_LsaClearPrivileges( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaClearPrivileges *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type = NULL;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sid && !op->in.name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.name && !op->in.sid ) {
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->in.sid = user_sid;
+ }
+
+ hnd->status =
+ rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx,
+ op->in.pol, *( op->in.sid ),
+ True, 0, NULL );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
+}
- return CAC_SUCCESS;
+int cac_LsaSetPrivileges( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaAddPrivileges *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *user_sid = NULL;
+ enum lsa_SidType *type = NULL;
+
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.pol || !op->in.priv_names ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sid && !op->in.name ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.name && !op->in.sid ) {
+ /*lookup the SID */
+ hnd->status =
+ rpccli_lsa_lookup_names( pipe_hnd, mem_ctx,
+ op->in.pol, 1,
+ ( const char ** ) &( op->in.
+ name ),
+ NULL, &user_sid, &type );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->in.sid = user_sid;
+ }
+
+ /*first remove all privileges */
+ hnd->status =
+ rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx,
+ op->in.pol, *( op->in.sid ),
+ True, 0, NULL );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol,
+ *( op->in.sid ),
+ op->in.num_privs,
+ ( const char ** ) op->in.
+ priv_names );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-int cac_LsaGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSecurityObject *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_LsaGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct LsaGetSecurityObject *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- /*this is taken from rpcclient/cmd_lsarpc.c*/
- uint16 info_level = 4;
+ /*this is taken from rpcclient/cmd_lsarpc.c */
+ uint16 info_level = 4;
- SEC_DESC_BUF *sec_out = NULL;
+ SEC_DESC_BUF *sec_out = NULL;
- if(!hnd) {
- return CAC_FAILURE;
- }
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.pol) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.pol ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_LSARPC );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_lsa_query_secobj( pipe_hnd, mem_ctx, op->in.pol, info_level, &sec_out);
+ hnd->status =
+ rpccli_lsa_query_secobj( pipe_hnd, mem_ctx, op->in.pol,
+ info_level, &sec_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.sec = sec_out;
+ op->out.sec = sec_out;
- return CAC_FAILURE;
+ return CAC_FAILURE;
}
diff --git a/source/libmsrpc/cac_samr.c b/source/libmsrpc/cac_samr.c
index 60c6562988e..e85142af906 100644
--- a/source/libmsrpc/cac_samr.c
+++ b/source/libmsrpc/cac_samr.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation (SAMR pipe)
@@ -29,2383 +30,2654 @@
/*not sure what this is.. taken from rpcclient/cmd_samr.c*/
#define SAMR_LOOKUP_FLAGS 0x000003e8
-int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *sam_out = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || op->in.access == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
-
- /*initialize for samr pipe if we have to*/
- if(!hnd->_internal.pipes[PI_SAMR]) {
- if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) {
- return CAC_FAILURE;
- }
-
- hnd->_internal.pipes[PI_SAMR] = True;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- sam_out = talloc(mem_ctx, POLICY_HND);
- if(!sam_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ uint32 des_access );
+
+int cac_SamConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamConnect *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND *sam_out = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || op->in.access == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ /*initialize for samr pipe if we have to */
+ if ( !hnd->_internal.pipes[PI_SAMR] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
+ &hnd->status ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_SAMR] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ sam_out = talloc( mem_ctx, POLICY_HND );
+ if ( !sam_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ if ( hnd->_internal.srv_level >= SRV_WIN_2K_SP3 ) {
+ hnd->status =
+ rpccli_samr_connect4( pipe_hnd, mem_ctx,
+ op->in.access, sam_out );
+ }
+
+ if ( hnd->_internal.srv_level < SRV_WIN_2K_SP3
+ || !NT_STATUS_IS_OK( hnd->status ) ) {
+ /*if sam_connect4 failed, the use sam_connect and lower srv_level */
+
+ hnd->status =
+ rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access,
+ sam_out );
+
+ if ( NT_STATUS_IS_OK( hnd->status )
+ && hnd->_internal.srv_level > SRV_WIN_2K ) {
+ hnd->_internal.srv_level = SRV_WIN_2K;
+ }
+ }
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->out.sam = sam_out;
+
+ return CAC_SUCCESS;
+}
- if(hnd->_internal.srv_level >= SRV_WIN_2K_SP3) {
- hnd->status = rpccli_samr_connect4( pipe_hnd, mem_ctx, op->in.access, sam_out);
- }
+int cac_SamClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * sam )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(hnd->_internal.srv_level < SRV_WIN_2K_SP3 || !NT_STATUS_IS_OK(hnd->status)) {
- /*if sam_connect4 failed, the use sam_connect and lower srv_level*/
+ if ( !hnd )
+ return CAC_FAILURE;
- hnd->status = rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access, sam_out);
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_2K) {
- hnd->_internal.srv_level = SRV_WIN_2K;
- }
- }
+ if ( !sam || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- op->out.sam = sam_out;
+ hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam );
- return CAC_SUCCESS;
-}
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
-int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!sam || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
/*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do)
* cac_SamOpenDomain() is the only function that calls it, so I just put the definition here
*/
+
/*attempts to find the sid of the domain we are connected to*/
-DOM_SID *cac_get_domain_sid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, uint32 des_access) {
- struct LsaOpenPolicy lop;
- struct LsaFetchSid fs;
+DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ uint32 des_access )
+{
+ struct LsaOpenPolicy lop;
+ struct LsaFetchSid fs;
+
+ DOM_SID *sid;
+
+ ZERO_STRUCT( lop );
+ ZERO_STRUCT( fs );
- DOM_SID *sid;
-
- ZERO_STRUCT(lop);
- ZERO_STRUCT(fs);
+ lop.in.access = des_access;
+ lop.in.security_qos = True;
- lop.in.access = des_access;
- lop.in.security_qos = True;
+ if ( !cac_LsaOpenPolicy( hnd, mem_ctx, &lop ) )
+ return NULL;
- if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop))
- return NULL;
+ fs.in.pol = lop.out.pol;
+ fs.in.info_class = CAC_DOMAIN_INFO;
- fs.in.pol = lop.out.pol;
- fs.in.info_class = CAC_DOMAIN_INFO;
+ if ( !cac_LsaFetchSid( hnd, mem_ctx, &fs ) )
+ return NULL;
- if(!cac_LsaFetchSid(hnd, mem_ctx, &fs))
- return NULL;
-
- cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol);
+ cac_LsaClosePolicy( hnd, mem_ctx, lop.out.pol );
- if(!fs.out.domain_sid)
- return NULL;
+ if ( !fs.out.domain_sid )
+ return NULL;
- sid = talloc_memdup(mem_ctx, &(fs.out.domain_sid->sid), sizeof(DOM_SID));
+ sid = ( DOM_SID * ) talloc_memdup( mem_ctx,
+ &( fs.out.domain_sid->sid ),
+ sizeof( DOM_SID ) );
- if(!sid) {
- hnd->status = NT_STATUS_NO_MEMORY;
- }
+ if ( !sid ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ }
- return sid;
+ return sid;
}
-int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- DOM_SID *sid_buf;
- POLICY_HND *sam_out;
- POLICY_HND *pol_out;
-
- struct SamLookupDomain sld;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || op->in.access == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.sam) {
- /*use cac_SamConnect() since it does the session setup*/
- struct SamConnect sc;
- ZERO_STRUCT(sc);
-
- sc.in.access = op->in.access;
-
- if(!cac_SamConnect(hnd, mem_ctx, &sc)) {
- return CAC_FAILURE;
- }
-
- sam_out = sc.out.sam;
- }
- else {
- sam_out = op->in.sam;
- }
-
- if(!op->in.sid) {
- /*find the sid for the SAM's domain*/
-
- /*try using cac_SamLookupDomain() first*/
- ZERO_STRUCT(sld);
-
- sld.in.sam = sam_out;
- sld.in.name = hnd->domain;
-
- if(cac_SamLookupDomain(hnd, mem_ctx, &sld)) {
- /*then we got the sid*/
- sid_buf = sld.out.sid;
- }
- else {
- /*try to get it from the LSA*/
- sid_buf = cac_get_domain_sid(hnd, mem_ctx, op->in.access);
- }
- }
- else {
- /*we already have the sid for the domain we want*/
- sid_buf = op->in.sid;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- pol_out = talloc(mem_ctx, POLICY_HND);
- if(!pol_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- /*now open the domain*/
- hnd->status = rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out, op->in.access, sid_buf, pol_out);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->out.sam = sam_out;
- op->out.dom_hnd = pol_out;
-
- return CAC_SUCCESS;
+int cac_SamOpenDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamOpenDomain *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *sid_buf;
+ POLICY_HND *sam_out;
+ POLICY_HND *pol_out;
+
+ struct SamLookupDomain sld;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || op->in.access == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.sam ) {
+ /*use cac_SamConnect() since it does the session setup */
+ struct SamConnect sc;
+
+ ZERO_STRUCT( sc );
+
+ sc.in.access = op->in.access;
+
+ if ( !cac_SamConnect( hnd, mem_ctx, &sc ) ) {
+ return CAC_FAILURE;
+ }
+
+ sam_out = sc.out.sam;
+ } else {
+ sam_out = op->in.sam;
+ }
+
+ if ( !op->in.sid ) {
+ /*find the sid for the SAM's domain */
+
+ /*try using cac_SamLookupDomain() first */
+ ZERO_STRUCT( sld );
+
+ sld.in.sam = sam_out;
+ sld.in.name = hnd->domain;
+
+ if ( cac_SamLookupDomain( hnd, mem_ctx, &sld ) ) {
+ /*then we got the sid */
+ sid_buf = sld.out.sid;
+ } else {
+ /*try to get it from the LSA */
+ sid_buf =
+ cac_get_domain_sid( hnd, mem_ctx,
+ op->in.access );
+ }
+ } else {
+ /*we already have the sid for the domain we want */
+ sid_buf = op->in.sid;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ pol_out = talloc( mem_ctx, POLICY_HND );
+ if ( !pol_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ /*now open the domain */
+ hnd->status =
+ rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out,
+ op->in.access, sid_buf, pol_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->out.sam = sam_out;
+ op->out.dom_hnd = pol_out;
+
+ return CAC_SUCCESS;
}
-int cac_SamOpenUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenUser *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamOpenUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamOpenUser *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 *rid_buf = NULL;
+ uint32 *rid_buf = NULL;
- uint32 num_rids = 0;
- uint32 *rid_types = NULL;
+ uint32 num_rids = 0;
+ uint32 *rid_types = NULL;
- POLICY_HND *user_out = NULL;
+ POLICY_HND *user_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(op->in.rid == 0 && op->in.name == NULL) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( op->in.rid == 0 && op->in.name == NULL ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(op->in.rid == 0 && op->in.name) {
- /*lookup the name and then set rid_buf*/
+ if ( op->in.rid == 0 && op->in.name ) {
+ /*lookup the name and then set rid_buf */
- hnd->status = rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, 1, (const char **)&op->in.name,
- &num_rids, &rid_buf, &rid_types);
+ hnd->status =
+ rpccli_samr_lookup_names( pipe_hnd, mem_ctx,
+ op->in.dom_hnd,
+ SAMR_LOOKUP_FLAGS, 1,
+ ( const char ** ) &op->in.
+ name, &num_rids, &rid_buf,
+ &rid_types );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(num_rids == 0 || rid_buf == NULL || rid_types[0] == SAMR_RID_UNKNOWN) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( num_rids == 0 || rid_buf == NULL
+ || rid_types[0] == SAMR_RID_UNKNOWN ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- TALLOC_FREE(rid_types);
+ TALLOC_FREE( rid_types );
- }
- else {
- rid_buf = &op->in.rid;
- }
+ } else {
+ rid_buf = &op->in.rid;
+ }
- user_out = talloc(mem_ctx, POLICY_HND);
- if(!user_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ user_out = talloc( mem_ctx, POLICY_HND );
+ if ( !user_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_open_user(pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, *rid_buf, user_out);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ hnd->status =
+ rpccli_samr_open_user( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ op->in.access, *rid_buf, user_out );
- op->out.user_hnd = user_out;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ op->out.user_hnd = user_out;
+
+ return CAC_SUCCESS;
}
-int cac_SamCreateUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateUser *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamCreateUser *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *user_out = NULL;
- uint32 rid_out;
+ POLICY_HND *user_out = NULL;
+ uint32 rid_out;
/**found in rpcclient/cmd_samr.c*/
- uint32 unknown = 0xe005000b;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- user_out = talloc(mem_ctx, POLICY_HND);
- if(!user_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_samr_create_dom_user( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, op->in.acb_mask, unknown, user_out, &rid_out);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->out.user_hnd = user_out;
- op->out.rid = rid_out;
-
- return CAC_SUCCESS;
+ uint32 unknown = 0xe005000b;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0
+ || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ user_out = talloc( mem_ctx, POLICY_HND );
+ if ( !user_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_samr_create_dom_user( pipe_hnd, mem_ctx,
+ op->in.dom_hnd, op->in.name,
+ op->in.acb_mask, unknown,
+ user_out, &rid_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->out.user_hnd = user_out;
+ op->out.rid = rid_out;
+
+ return CAC_SUCCESS;
}
-int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamDeleteUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * user_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!user_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !user_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd);
+ hnd->status =
+ rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamEnumUsers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumUsers *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamEnumUsers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamEnumUsers *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 resume_idx_out = 0;
- char **names_out = NULL;
- uint32 *rids_out = NULL;
- uint32 num_users_out = 0;
+ uint32 resume_idx_out = 0;
+ char **names_out = NULL;
+ uint32 *rids_out = NULL;
+ uint32 num_users_out = 0;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
- if(op->out.done == True)
- return CAC_FAILURE;
+ /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
+ if ( op->out.done == True )
+ return CAC_FAILURE;
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- resume_idx_out = op->out.resume_idx;
+ resume_idx_out = op->out.resume_idx;
- hnd->status = rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.acb_mask, SAMR_ENUM_MAX_SIZE,
- &names_out, &rids_out, &num_users_out);
+ hnd->status =
+ rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ &resume_idx_out, op->in.acb_mask,
+ SAMR_ENUM_MAX_SIZE, &names_out,
+ &rids_out, &num_users_out );
- if(NT_STATUS_IS_OK(hnd->status))
- op->out.done = True;
+ if ( NT_STATUS_IS_OK( hnd->status ) )
+ op->out.done = True;
- /*if there are no more entries, the operation will return NT_STATUS_OK.
- * We want to return failure if no results were returned*/
- if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
- return CAC_FAILURE;
+ /*if there are no more entries, the operation will return NT_STATUS_OK.
+ * We want to return failure if no results were returned*/
+ if ( !NT_STATUS_IS_OK( hnd->status )
+ && NT_STATUS_V( hnd->status ) !=
+ NT_STATUS_V( STATUS_MORE_ENTRIES ) )
+ return CAC_FAILURE;
- op->out.resume_idx= resume_idx_out;
- op->out.num_users = num_users_out;
- op->out.rids = rids_out;
- op->out.names = names_out;
+ op->out.resume_idx = resume_idx_out;
+ op->out.num_users = num_users_out;
+ op->out.rids = rids_out;
+ op->out.names = names_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetNamesFromRids *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- uint32 num_names_out;
- char **names_out;
- uint32 *name_types_out;
-
-
- uint32 i = 0;
-
- CacLookupRidsRecord *map_out;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.rids && op->in.num_rids != 0) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(op->in.num_rids == 0) {
- /*nothing to do*/
- op->out.num_names = 0;
- return CAC_SUCCESS;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_samr_lookup_rids( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.num_rids, op->in.rids, &num_names_out, &names_out, &name_types_out);
-
- if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
- return CAC_FAILURE;
-
- map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_names_out);
- if(!map_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_names_out; i++) {
- if(name_types_out[i] == SAMR_RID_UNKNOWN) {
- map_out[i].found = False;
- map_out[i].name = NULL;
- map_out[i].type = 0;
- }
- else {
- map_out[i].found = True;
- map_out[i].name = talloc_strdup(mem_ctx, names_out[i]);
- map_out[i].type = name_types_out[i];
- }
- map_out[i].rid = op->in.rids[i];
- }
-
- TALLOC_FREE(names_out);
- TALLOC_FREE(name_types_out);
-
- op->out.num_names = num_names_out;
- op->out.map = map_out;
-
- if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
- return CAC_PARTIAL_SUCCESS;
-
- return CAC_SUCCESS;
+int cac_SamGetNamesFromRids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetNamesFromRids *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 num_names_out;
+ char **names_out;
+ uint32 *name_types_out;
+
+
+ uint32 i = 0;
+
+ CacLookupRidsRecord *map_out;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.rids && op->in.num_rids != 0 ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.num_rids == 0 ) {
+ /*nothing to do */
+ op->out.num_names = 0;
+ return CAC_SUCCESS;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_samr_lookup_rids( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ op->in.num_rids, op->in.rids,
+ &num_names_out, &names_out,
+ &name_types_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status )
+ && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
+ return CAC_FAILURE;
+
+ map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_names_out );
+ if ( !map_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_names_out; i++ ) {
+ if ( name_types_out[i] == SAMR_RID_UNKNOWN ) {
+ map_out[i].found = False;
+ map_out[i].name = NULL;
+ map_out[i].type = 0;
+ } else {
+ map_out[i].found = True;
+ map_out[i].name =
+ talloc_strdup( mem_ctx, names_out[i] );
+ map_out[i].type = name_types_out[i];
+ }
+ map_out[i].rid = op->in.rids[i];
+ }
+
+ TALLOC_FREE( names_out );
+ TALLOC_FREE( name_types_out );
+
+ op->out.num_names = num_names_out;
+ op->out.map = map_out;
+
+ if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
+ return CAC_PARTIAL_SUCCESS;
+
+ return CAC_SUCCESS;
}
-int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- uint32 num_rids_out;
- uint32 *rids_out;
- uint32 *rid_types_out;
-
- uint32 i = 0;
-
- CacLookupRidsRecord *map_out;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(!op->in.names && op->in.num_names != 0) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- if(op->in.num_names == 0) {
- /*then we don't have to do anything*/
- op->out.num_rids = 0;
- return CAC_SUCCESS;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- hnd->status = rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, op->in.num_names, (const char **)op->in.names,
- &num_rids_out, &rids_out, &rid_types_out);
-
- if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
- return CAC_FAILURE;
-
- map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_rids_out);
- if(!map_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_rids_out; i++) {
-
- if(rid_types_out[i] == SAMR_RID_UNKNOWN) {
- map_out[i].found = False;
- map_out[i].rid = 0;
- map_out[i].type = 0;
- }
- else {
- map_out[i].found = True;
- map_out[i].rid = rids_out[i];
- map_out[i].type = rid_types_out[i];
- }
-
- map_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]);
- }
-
- op->out.num_rids = num_rids_out;
- op->out.map = map_out;
-
- TALLOC_FREE(rids_out);
- TALLOC_FREE(rid_types_out);
-
- if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
- return CAC_PARTIAL_SUCCESS;
-
- return CAC_SUCCESS;
+int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetRidsFromNames *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 num_rids_out;
+ uint32 *rids_out;
+ uint32 *rid_types_out;
+
+ uint32 i = 0;
+
+ CacLookupRidsRecord *map_out;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.names && op->in.num_names != 0 ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.num_names == 0 ) {
+ /*then we don't have to do anything */
+ op->out.num_rids = 0;
+ return CAC_SUCCESS;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ SAMR_LOOKUP_FLAGS, op->in.num_names,
+ ( const char ** ) op->in.names,
+ &num_rids_out, &rids_out,
+ &rid_types_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status )
+ && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
+ return CAC_FAILURE;
+
+ map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_rids_out );
+ if ( !map_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_rids_out; i++ ) {
+
+ if ( rid_types_out[i] == SAMR_RID_UNKNOWN ) {
+ map_out[i].found = False;
+ map_out[i].rid = 0;
+ map_out[i].type = 0;
+ } else {
+ map_out[i].found = True;
+ map_out[i].rid = rids_out[i];
+ map_out[i].type = rid_types_out[i];
+ }
+
+ map_out[i].name = talloc_strdup( mem_ctx, op->in.names[i] );
+ }
+
+ op->out.num_rids = num_rids_out;
+ op->out.map = map_out;
+
+ TALLOC_FREE( rids_out );
+ TALLOC_FREE( rid_types_out );
+
+ if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
+ return CAC_PARTIAL_SUCCESS;
+
+ return CAC_SUCCESS;
}
-int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupsForUser *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetGroupsForUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetGroupsForUser *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_GID *groups = NULL;
+ uint32 num_groups_out = 0;
- DOM_GID *groups = NULL;
- uint32 num_groups_out = 0;
+ uint32 *rids_out = NULL;
+ uint32 *attr_out = NULL;
- uint32 *rids_out = NULL;
- uint32 *attr_out = NULL;
+ uint32 i;
- uint32 i;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.user_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.user_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ hnd->status =
+ rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
+ op->in.user_hnd,
+ &num_groups_out, &groups );
- hnd->status = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, op->in.user_hnd, &num_groups_out, &groups);
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ rids_out = talloc_array( mem_ctx, uint32, num_groups_out );
+ if ( !rids_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
- if(!rids_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ attr_out = talloc_array( mem_ctx, uint32, num_groups_out );
+ if ( !attr_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- attr_out = talloc_array(mem_ctx, uint32, num_groups_out);
- if(!attr_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_groups_out; i++) {
- rids_out[i] = groups[i].g_rid;
- attr_out[i] = groups[i].attr;
- }
+ for ( i = 0; i < num_groups_out; i++ ) {
+ rids_out[i] = groups[i].g_rid;
+ attr_out[i] = groups[i].attr;
+ }
- TALLOC_FREE(groups);
+ TALLOC_FREE( groups );
- op->out.num_groups = num_groups_out;
- op->out.rids = rids_out;
- op->out.attributes = attr_out;
+ op->out.num_groups = num_groups_out;
+ op->out.rids = rids_out;
+ op->out.attributes = attr_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamOpenGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenGroup *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamOpenGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamOpenGroup *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *group_hnd_out = NULL;
+ POLICY_HND *group_hnd_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- group_hnd_out = talloc(mem_ctx, POLICY_HND);
- if(!group_hnd_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ group_hnd_out = talloc( mem_ctx, POLICY_HND );
+ if ( !group_hnd_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, group_hnd_out);
+ hnd->status =
+ rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ op->in.access, op->in.rid,
+ group_hnd_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.group_hnd = group_hnd_out;
+ op->out.group_hnd = group_hnd_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamCreateGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateGroup *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamCreateGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamCreateGroup *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *group_hnd_out = NULL;
+ POLICY_HND *group_hnd_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.name || op->in.name[0] == '\0' || op->in.access == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.name || op->in.name[0] == '\0'
+ || op->in.access == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- group_hnd_out = talloc(mem_ctx, POLICY_HND);
- if(!group_hnd_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ group_hnd_out = talloc( mem_ctx, POLICY_HND );
+ if ( !group_hnd_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_create_dom_group( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, op->in.access, group_hnd_out);
+ hnd->status =
+ rpccli_samr_create_dom_group( pipe_hnd, mem_ctx,
+ op->in.dom_hnd, op->in.name,
+ op->in.access, group_hnd_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.group_hnd = group_hnd_out;
+ op->out.group_hnd = group_hnd_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * group_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!group_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !group_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd);
+ hnd->status =
+ rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetGroupMembers *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 num_mem_out;
- uint32 *rids_out;
- uint32 *attr_out;
+ uint32 num_mem_out;
+ uint32 *rids_out;
+ uint32 *attr_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.group_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.group_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, &num_mem_out, &rids_out, &attr_out);
+ hnd->status =
+ rpccli_samr_query_groupmem( pipe_hnd, mem_ctx,
+ op->in.group_hnd, &num_mem_out,
+ &rids_out, &attr_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.num_members = num_mem_out;
- op->out.rids = rids_out;
- op->out.attributes = attr_out;
+ op->out.num_members = num_mem_out;
+ op->out.rids = rids_out;
+ op->out.attributes = attr_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamAddGroupMember *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rid);
+ hnd->status =
+ rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
+ op->in.rid );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamRemoveGroupMember *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rid);
+ hnd->status =
+ rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
+ op->in.rid );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamClearGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * group_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- int result = CAC_SUCCESS;
+ int result = CAC_SUCCESS;
- int i = 0;
+ int i = 0;
- uint32 num_mem = 0;
- uint32 *rid = NULL;
- uint32 *attr = NULL;
+ uint32 num_mem = 0;
+ uint32 *rid = NULL;
+ uint32 *attr = NULL;
- NTSTATUS status;
+ NTSTATUS status;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!group_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !group_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, group_hnd, &num_mem, &rid, &attr);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ hnd->status =
+ rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
+ &num_mem, &rid, &attr );
- /*try to delete the users one by one*/
- for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
- hnd->status = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, group_hnd, rid[i]);
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- /*if not all members could be removed, then try to re-add the members that were already deleted*/
- if(!NT_STATUS_IS_OK(hnd->status)) {
- status = NT_STATUS_OK;
+ /*try to delete the users one by one */
+ for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
+ hnd->status =
+ rpccli_samr_del_groupmem( pipe_hnd, mem_ctx,
+ group_hnd, rid[i] );
+ }
- for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
- status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, group_hnd, rid[i]);
- }
+ /*if not all members could be removed, then try to re-add the members that were already deleted */
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ status = NT_STATUS_OK;
- /*we return with the NTSTATUS error that we got when trying to delete users*/
- if(!NT_STATUS_IS_OK(status))
- result = CAC_FAILURE;
- }
+ for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
+ status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
+ group_hnd,
+ rid[i] );
+ }
- TALLOC_FREE(attr);
+ /*we return with the NTSTATUS error that we got when trying to delete users */
+ if ( !NT_STATUS_IS_OK( status ) )
+ result = CAC_FAILURE;
+ }
- return result;
+ TALLOC_FREE( attr );
+
+ return result;
}
-int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetGroupMembers *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 i = 0;
- uint32 i = 0;
-
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.group_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.group_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- /*use cac_SamClearGroupMembers() to clear them*/
- if(!cac_SamClearGroupMembers(hnd, mem_ctx, op->in.group_hnd))
- return CAC_FAILURE; /*hnd->status is already set*/
+ /*use cac_SamClearGroupMembers() to clear them */
+ if ( !cac_SamClearGroupMembers( hnd, mem_ctx, op->in.group_hnd ) )
+ return CAC_FAILURE; /*hnd->status is already set */
- for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
- hnd->status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rids[i]);
- }
+ for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
+ i++ ) {
+ hnd->status =
+ rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
+ op->in.group_hnd,
+ op->in.rids[i] );
+ }
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- uint32 i = 0;
-
- uint32 resume_idx_out = 0;
- char **names_out = NULL;
- char **desc_out = NULL;
- uint32 *rids_out = NULL;
- uint32 num_groups_out = 0;
-
- struct acct_info *acct_buf = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- /*using this BOOL is the only reliable way to know that we are done*/
- if(op->out.done == True) /*we return failure so the call will break out of a loop*/
- return CAC_FAILURE;
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- resume_idx_out = op->out.resume_idx;
-
- hnd->status = rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
- &acct_buf, &num_groups_out);
-
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- op->out.done = True;
- }
- else if(NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
- /*if there are no more entries, the operation will return NT_STATUS_OK.
- * We want to return failure if no results were returned*/
- return CAC_FAILURE;
- }
-
- names_out = talloc_array(mem_ctx, char *, num_groups_out);
- if(!names_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- return CAC_FAILURE;
- }
-
- desc_out = talloc_array(mem_ctx, char *, num_groups_out);
- if(!desc_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- TALLOC_FREE(names_out);
- return CAC_FAILURE;
- }
-
- rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
- if(!rids_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- TALLOC_FREE(names_out);
- TALLOC_FREE(desc_out);
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_groups_out; i++) {
- names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
- desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
- rids_out[i] = acct_buf[i].rid;
-
- if(!names_out[i] || !desc_out[i]) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
- }
-
- op->out.resume_idx = resume_idx_out;
- op->out.num_groups = num_groups_out;
- op->out.rids = rids_out;
- op->out.names = names_out;
- op->out.descriptions = desc_out;
-
- return CAC_SUCCESS;
+int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamEnumGroups *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 i = 0;
+
+ uint32 resume_idx_out = 0;
+ char **names_out = NULL;
+ char **desc_out = NULL;
+ uint32 *rids_out = NULL;
+ uint32 num_groups_out = 0;
+
+ struct acct_info *acct_buf = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ /*using this BOOL is the only reliable way to know that we are done */
+ if ( op->out.done == True ) /*we return failure so the call will break out of a loop */
+ return CAC_FAILURE;
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ resume_idx_out = op->out.resume_idx;
+
+ hnd->status =
+ rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx,
+ op->in.dom_hnd, &resume_idx_out,
+ SAMR_ENUM_MAX_SIZE, &acct_buf,
+ &num_groups_out );
+
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ op->out.done = True;
+ } else if ( NT_STATUS_V( hnd->status ) !=
+ NT_STATUS_V( STATUS_MORE_ENTRIES ) ) {
+ /*if there are no more entries, the operation will return NT_STATUS_OK.
+ * We want to return failure if no results were returned*/
+ return CAC_FAILURE;
+ }
+
+ names_out = talloc_array( mem_ctx, char *, num_groups_out );
+ if ( !names_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ return CAC_FAILURE;
+ }
+
+ desc_out = talloc_array( mem_ctx, char *, num_groups_out );
+ if ( !desc_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ TALLOC_FREE( names_out );
+ return CAC_FAILURE;
+ }
+
+ rids_out = talloc_array( mem_ctx, uint32, num_groups_out );
+ if ( !rids_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ TALLOC_FREE( names_out );
+ TALLOC_FREE( desc_out );
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_groups_out; i++ ) {
+ names_out[i] =
+ talloc_strdup( mem_ctx, acct_buf[i].acct_name );
+ desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
+ rids_out[i] = acct_buf[i].rid;
+
+ if ( !names_out[i] || !desc_out[i] ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+ }
+
+ op->out.resume_idx = resume_idx_out;
+ op->out.num_groups = num_groups_out;
+ op->out.rids = rids_out;
+ op->out.names = names_out;
+ op->out.descriptions = desc_out;
+
+ return CAC_SUCCESS;
}
-int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- uint32 i = 0;
-
- uint32 resume_idx_out = 0;
- char **names_out = NULL;
- char **desc_out = NULL;
- uint32 *rids_out = NULL;
- uint32 num_als_out = 0;
-
- struct acct_info *acct_buf = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
- if(op->out.done == True) {
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- resume_idx_out = op->out.resume_idx;
-
- hnd->status = rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
- &acct_buf, &num_als_out);
-
-
- if(NT_STATUS_IS_OK(hnd->status))
- op->out.done = True;
-
- /*if there are no more entries, the operation will return NT_STATUS_OK.
- * We want to return failure if no results were returned*/
- if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
- return CAC_FAILURE;
-
- names_out = talloc_array(mem_ctx, char *, num_als_out);
- if(!names_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- return CAC_FAILURE;
- }
-
- desc_out = talloc_array(mem_ctx, char *, num_als_out);
- if(!desc_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- TALLOC_FREE(names_out);
- return CAC_FAILURE;
- }
-
- rids_out = talloc_array(mem_ctx, uint32, num_als_out);
- if(!rids_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(acct_buf);
- TALLOC_FREE(names_out);
- TALLOC_FREE(desc_out);
- return CAC_FAILURE;
- }
-
- for(i = 0; i < num_als_out; i++) {
- names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
- desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
- rids_out[i] = acct_buf[i].rid;
-
- if(!names_out[i] || !desc_out[i]) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
- }
-
- op->out.resume_idx = resume_idx_out;
- op->out.num_aliases = num_als_out;
- op->out.rids = rids_out;
- op->out.names = names_out;
- op->out.descriptions = desc_out;
-
- return CAC_SUCCESS;
+int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamEnumAliases *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ uint32 i = 0;
+
+ uint32 resume_idx_out = 0;
+ char **names_out = NULL;
+ char **desc_out = NULL;
+ uint32 *rids_out = NULL;
+ uint32 num_als_out = 0;
+
+ struct acct_info *acct_buf = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
+ if ( op->out.done == True ) {
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ resume_idx_out = op->out.resume_idx;
+
+ hnd->status =
+ rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx,
+ op->in.dom_hnd, &resume_idx_out,
+ SAMR_ENUM_MAX_SIZE, &acct_buf,
+ &num_als_out );
+
+
+ if ( NT_STATUS_IS_OK( hnd->status ) )
+ op->out.done = True;
+
+ /*if there are no more entries, the operation will return NT_STATUS_OK.
+ * We want to return failure if no results were returned*/
+ if ( !NT_STATUS_IS_OK( hnd->status )
+ && NT_STATUS_V( hnd->status ) !=
+ NT_STATUS_V( STATUS_MORE_ENTRIES ) )
+ return CAC_FAILURE;
+
+ names_out = talloc_array( mem_ctx, char *, num_als_out );
+ if ( !names_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ return CAC_FAILURE;
+ }
+
+ desc_out = talloc_array( mem_ctx, char *, num_als_out );
+ if ( !desc_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ TALLOC_FREE( names_out );
+ return CAC_FAILURE;
+ }
+
+ rids_out = talloc_array( mem_ctx, uint32, num_als_out );
+ if ( !rids_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( acct_buf );
+ TALLOC_FREE( names_out );
+ TALLOC_FREE( desc_out );
+ return CAC_FAILURE;
+ }
+
+ for ( i = 0; i < num_als_out; i++ ) {
+ names_out[i] =
+ talloc_strdup( mem_ctx, acct_buf[i].acct_name );
+ desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
+ rids_out[i] = acct_buf[i].rid;
+
+ if ( !names_out[i] || !desc_out[i] ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+ }
+
+ op->out.resume_idx = resume_idx_out;
+ op->out.num_aliases = num_als_out;
+ op->out.rids = rids_out;
+ op->out.names = names_out;
+ op->out.descriptions = desc_out;
+
+ return CAC_SUCCESS;
}
-int cac_SamCreateAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateAlias *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamCreateAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamCreateAlias *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *als_hnd_out = NULL;
+ POLICY_HND *als_hnd_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- als_hnd_out = talloc(mem_ctx, POLICY_HND);
- if(!als_hnd_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ als_hnd_out = talloc( mem_ctx, POLICY_HND );
+ if ( !als_hnd_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, als_hnd_out);
+ hnd->status =
+ rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx,
+ op->in.dom_hnd, op->in.name,
+ als_hnd_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.alias_hnd = als_hnd_out;
+ op->out.alias_hnd = als_hnd_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamOpenAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenAlias *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamOpenAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamOpenAlias *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *als_hnd_out = NULL;
+ POLICY_HND *als_hnd_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- als_hnd_out = talloc(mem_ctx, POLICY_HND);
- if(!als_hnd_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ als_hnd_out = talloc( mem_ctx, POLICY_HND );
+ if ( !als_hnd_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, als_hnd_out);
+ hnd->status =
+ rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ op->in.access, op->in.rid,
+ als_hnd_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.alias_hnd = als_hnd_out;
+ op->out.alias_hnd = als_hnd_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * alias_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!alias_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !alias_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd);
+ hnd->status =
+ rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamAddAliasMember *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, op->in.sid);
+ hnd->status =
+ rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
+ op->in.sid );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamRemoveAliasMember *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, op->in.sid);
+ hnd->status =
+ rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
+ op->in.sid );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetAliasMembers *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- uint32 num_mem_out;
- DOM_SID *sids_out;
+ uint32 num_mem_out;
+ DOM_SID *sids_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.alias_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.alias_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, &num_mem_out, &sids_out);
+ hnd->status =
+ rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
+ op->in.alias_hnd, &num_mem_out,
+ &sids_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.num_members = num_mem_out;
- op->out.sids = sids_out;
+ op->out.num_members = num_mem_out;
+ op->out.sids = sids_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- int result = CAC_SUCCESS;
-
- int i = 0;
-
- uint32 num_mem = 0;
- DOM_SID *sid = NULL;
-
- NTSTATUS status;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!alias_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+int cac_SamClearAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * alias_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- hnd->status = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, alias_hnd, &num_mem, &sid);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ int result = CAC_SUCCESS;
- /*try to delete the users one by one*/
- for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
- hnd->status = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, alias_hnd, &sid[i]);
- }
+ int i = 0;
- /*if not all members could be removed, then try to re-add the members that were already deleted*/
- if(!NT_STATUS_IS_OK(hnd->status)) {
- status = NT_STATUS_OK;
+ uint32 num_mem = 0;
+ DOM_SID *sid = NULL;
- for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
- status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, alias_hnd, &sid[i]);
- }
+ NTSTATUS status;
- /*we return with the NTSTATUS error that we got when trying to delete users*/
- if(!NT_STATUS_IS_OK(status))
- result = CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- TALLOC_FREE(sid);
- return result;
-}
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
-int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+ if ( !alias_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- uint32 i = 0;
-
- if(!hnd)
- return CAC_FAILURE;
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ hnd->status =
+ rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
+ &num_mem, &sid );
- if(!op || !op->in.alias_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ /*try to delete the users one by one */
+ for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
+ hnd->status =
+ rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx,
+ alias_hnd, &sid[i] );
+ }
- /*use cac_SamClearAliasMembers() to clear them*/
- if(!cac_SamClearAliasMembers(hnd, mem_ctx, op->in.alias_hnd))
- return CAC_FAILURE; /*hnd->status is already set*/
+ /*if not all members could be removed, then try to re-add the members that were already deleted */
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ status = NT_STATUS_OK;
+ for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
+ status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
+ alias_hnd,
+ &sid[i] );
+ }
- for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
- hnd->status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, &(op->in.sids[i]));
- }
+ /*we return with the NTSTATUS error that we got when trying to delete users */
+ if ( !NT_STATUS_IS_OK( status ) )
+ result = CAC_FAILURE;
+ }
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ TALLOC_FREE( sid );
+ return result;
+}
- return CAC_SUCCESS;
+int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetAliasMembers *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
-}
+ uint32 i = 0;
-int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamUserChangePasswd *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.alias_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.username || !op->in.password || !op->in.new_password || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ /*use cac_SamClearAliasMembers() to clear them */
+ if ( !cac_SamClearAliasMembers( hnd, mem_ctx, op->in.alias_hnd ) )
+ return CAC_FAILURE; /*hnd->status is already set */
- /*open a session on SAMR if we don't have one*/
- if(!hnd->_internal.pipes[PI_SAMR]) {
- if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SAMR, &(hnd->status)))) {
- return CAC_FAILURE;
- }
- hnd->_internal.pipes[PI_SAMR] = True;
- }
+ for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
+ i++ ) {
+ hnd->status =
+ rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
+ op->in.alias_hnd,
+ &( op->in.sids[i] ) );
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- hnd->status = rpccli_samr_chgpasswd_user(pipe_hnd, mem_ctx, op->in.username, op->in.new_password, op->in.password);
+ return CAC_SUCCESS;
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+}
- return CAC_SUCCESS;
+int cac_SamUserChangePasswd( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamUserChangePasswd *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.username || !op->in.password
+ || !op->in.new_password || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ /*open a session on SAMR if we don't have one */
+ if ( !hnd->_internal.pipes[PI_SAMR] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
+ &hnd->status ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_SAMR] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_samr_chgpasswd_user( pipe_hnd, mem_ctx,
+ op->in.username,
+ op->in.new_password,
+ op->in.password );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ return CAC_SUCCESS;
}
-int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamEnableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * user_hnd )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
- SAM_USERINFO_CTR *ctr;
+ SAM_USERINFO_CTR *ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!user_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !user_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked.*/
- hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10, &ctr);
+ /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked. */
+ hnd->status =
+ rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
+ &ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
/**check the ACB mask*/
- if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
- /*toggle the disabled bit*/
- ctr->info.id16->acb_info ^= ACB_DISABLED;
- }
- else {
- /*the user is already enabled so just return success*/
- return CAC_SUCCESS;
- }
-
- /*now set the userinfo*/
- hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
-
- /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- return CAC_SUCCESS;
+ if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
+ /*toggle the disabled bit */
+ ctr->info.id16->acb_info ^= ACB_DISABLED;
+ } else {
+ /*the user is already enabled so just return success */
+ return CAC_SUCCESS;
+ }
+
+ /*now set the userinfo */
+ hnd->status =
+ rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
+ &srv->cli->user_session_key, ctr );
+
+ /*this will only work properly if we use set_userinfo2 - fail if it is not supported */
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ return CAC_SUCCESS;
}
-int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamDisableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * user_hnd )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
- SAM_USERINFO_CTR *ctr;
+ SAM_USERINFO_CTR *ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!user_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !user_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10, &ctr);
+ hnd->status =
+ rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
+ &ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
- /*then the user is already disabled*/
- return CAC_SUCCESS;
- }
+ if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
+ /*then the user is already disabled */
+ return CAC_SUCCESS;
+ }
- /*toggle the disabled bit*/
- ctr->info.id16->acb_info ^= ACB_DISABLED;
+ /*toggle the disabled bit */
+ ctr->info.id16->acb_info ^= ACB_DISABLED;
- /*this will only work properly if we use set_userinfo2*/
- hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
+ /*this will only work properly if we use set_userinfo2 */
+ hnd->status =
+ rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
+ &srv->cli->user_session_key, ctr );
- /*this will only work properly if we use set_userinfo2 fail if it is not supported*/
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ /*this will only work properly if we use set_userinfo2 fail if it is not supported */
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetPassword *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamSetPassword( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetPassword *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
- SAM_USERINFO_CTR ctr;
- SAM_USER_INFO_24 info24;
- uint8 pw[516];
+ SAM_USERINFO_CTR ctr;
+ SAM_USER_INFO_24 info24;
+ uint8 pw[516];
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.user_hnd || !op->in.password || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- ZERO_STRUCT(ctr);
- ZERO_STRUCT(info24);
+ ZERO_STRUCT( ctr );
+ ZERO_STRUCT( info24 );
- encode_pw_buffer(pw, op->in.password, STR_UNICODE);
+ encode_pw_buffer( pw, op->in.password, STR_UNICODE );
- init_sam_user_info24(&info24, (char *)pw, 24);
+ init_sam_user_info24( &info24, ( char * ) pw, 24 );
- ctr.switch_value = 24;
- ctr.info.id24 = &info24;
+ ctr.switch_value = 24;
+ ctr.info.id24 = &info24;
- hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &(srv->cli.user_session_key), &ctr);
+ hnd->status =
+ rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
+ 24, &srv->cli->user_session_key,
+ &ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetUserInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- SAM_USERINFO_CTR *ctr;
+ SAM_USERINFO_CTR *ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.user_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.user_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &ctr);
+ hnd->status =
+ rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
+ op->in.user_hnd, 21, &ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.info = cac_MakeUserInfo(mem_ctx, ctr);
+ op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
- if(!op->out.info) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ if ( !op->out.info ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfo *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- SAM_USERINFO_CTR *ctr;
-
- if(!hnd)
- return CAC_FAILURE;
+int cac_SamSetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetUserInfo *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ SAM_USERINFO_CTR *ctr;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
+ if ( !ctr ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( hnd->_internal.srv_level >= SRV_WIN_NT4 ) {
+ hnd->status =
+ rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx,
+ op->in.user_hnd, 21,
+ &srv->cli->
+ user_session_key, ctr );
+ }
+
+ if ( hnd->_internal.srv_level < SRV_WIN_NT4
+ || !NT_STATUS_IS_OK( hnd->status ) ) {
+ hnd->status =
+ rpccli_samr_set_userinfo( pipe_hnd, mem_ctx,
+ op->in.user_hnd, 21,
+ &srv->cli->user_session_key,
+ ctr );
+
+ if ( NT_STATUS_IS_OK( hnd->status )
+ && hnd->_internal.srv_level > SRV_WIN_NT4 ) {
+ hnd->_internal.srv_level = SRV_WIN_NT4;
+ }
+ }
+
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ return CAC_SUCCESS;
+}
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
- if(!op->in.user_hnd || !op->in.info || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+int cac_SamGetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetUserInfoCtr *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- ctr = cac_MakeUserInfoCtr(mem_ctx, op->in.info);
- if(!ctr) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ SAM_USERINFO_CTR *ctr_out;
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(hnd->_internal.srv_level >= SRV_WIN_NT4) {
- hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
- }
+ if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) {
- hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) {
- hnd->_internal.srv_level = SRV_WIN_NT4;
- }
- }
+ hnd->status =
+ rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
+ op->in.user_hnd,
+ op->in.info_class, &ctr_out );
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ op->out.ctr = ctr_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
+int cac_SamSetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetUserInfoCtr *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
-int cac_SamGetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfoCtr *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+ if ( !hnd )
+ return CAC_FAILURE;
- SAM_USERINFO_CTR *ctr_out;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd)
- return CAC_FAILURE;
+ if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
- if(!op->in.user_hnd || op->in.info_class == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
- hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.info_class, &ctr_out);
+ hnd->status =
+ rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
+ op->in.ctr->switch_value,
+ &srv->cli->user_session_key,
+ op->in.ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.ctr = ctr_out;
+ return CAC_SUCCESS;
- return CAC_SUCCESS;
}
-int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfoCtr *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+int cac_SamRenameUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamRenameUser *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!op->in.user_hnd || !op->in.ctr || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ SAM_USERINFO_CTR ctr;
+ SAM_USER_INFO_7 info7;
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+ if ( !op->in.user_hnd || !op->in.new_name
+ || op->in.new_name[0] == '\0' || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &(srv->cli.user_session_key), op->in.ctr);
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ ZERO_STRUCT( ctr );
+ ZERO_STRUCT( info7 );
-}
-
-int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameUser *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- SAM_USERINFO_CTR ctr;
- SAM_USER_INFO_7 info7;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ init_sam_user_info7( &info7, op->in.new_name );
- if(!op->in.user_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ ctr.switch_value = 7;
+ ctr.info.id7 = &info7;
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ hnd->status =
+ rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
+ 7, &srv->cli->user_session_key,
+ &ctr );
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- ZERO_STRUCT(ctr);
- ZERO_STRUCT(info7);
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- init_sam_user_info7(&info7, op->in.new_name);
-
- ctr.switch_value = 7;
- ctr.info.id7 = &info7;
-
- hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &(srv->cli.user_session_key), &ctr);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetGroupInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- GROUP_INFO_CTR *ctr;
+ GROUP_INFO_CTR *ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.group_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.group_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- /*get a GROUP_INFO_1 structure*/
- hnd->status = rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx, op->in.group_hnd, 1, &ctr);
+ /*get a GROUP_INFO_1 structure */
+ hnd->status =
+ rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx,
+ op->in.group_hnd, 1, &ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.info = cac_MakeGroupInfo(mem_ctx, ctr);
- if(!op->out.info) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ op->out.info = cac_MakeGroupInfo( mem_ctx, ctr );
+ if ( !op->out.info ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamSetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamSetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetGroupInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- GROUP_INFO_CTR *ctr = NULL;
+ GROUP_INFO_CTR *ctr = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.group_hnd || !op->in.info || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- ctr = cac_MakeGroupInfoCtr(mem_ctx, op->in.info);
- if(!ctr) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
+ if ( !ctr ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, op->in.group_hnd, ctr);
+ hnd->status =
+ rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
+ op->in.group_hnd, ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamRenameGroup *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- GROUP_INFO_CTR ctr;
+ GROUP_INFO_CTR ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.group_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.group_hnd || !op->in.new_name
+ || op->in.new_name[0] == '\0' || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- ZERO_STRUCT(ctr);
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- init_samr_group_info2(&ctr.group.info2, op->in.new_name);
- ctr.switch_value1 = 2;
-
- hnd->status = rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx, op->in.group_hnd, &ctr);
+ ZERO_STRUCT( ctr );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ init_samr_group_info2( &ctr.group.info2, op->in.new_name );
+ ctr.switch_value1 = 2;
- return CAC_SUCCESS;
-}
+ hnd->status =
+ rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
+ op->in.group_hnd, &ctr );
-int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- ALIAS_INFO_CTR ctr;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op->in.alias_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*get a GROUP_INFO_1 structure*/
- hnd->status = rpccli_samr_query_alias_info( pipe_hnd, mem_ctx, op->in.alias_hnd, 1, &ctr);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->out.info = cac_MakeAliasInfo(mem_ctx, ctr);
- if(!op->out.info) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+ return CAC_SUCCESS;
}
-int cac_SamSetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetAliasInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- ALIAS_INFO_CTR *ctr = NULL;
+ ALIAS_INFO_CTR ctr;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.alias_hnd || !op->in.info || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.alias_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- ctr = cac_MakeAliasInfoCtr(mem_ctx, op->in.info);
- if(!ctr) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ /*get a GROUP_INFO_1 structure */
+ hnd->status =
+ rpccli_samr_query_alias_info( pipe_hnd, mem_ctx,
+ op->in.alias_hnd, 1, &ctr );
- hnd->status = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, op->in.alias_hnd, ctr);
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ op->out.info = cac_MakeAliasInfo( mem_ctx, ctr );
+ if ( !op->out.info ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
-}
+ return CAC_SUCCESS;
-int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- SAM_UNK_CTR ctr;
- SAM_UNK_INFO_1 info1;
- SAM_UNK_INFO_2 info2;
- SAM_UNK_INFO_12 info12;
-
- /*use this to keep track of a failed call*/
- NTSTATUS status_buf = NT_STATUS_OK;
-
- uint16 fail_count = 0;
-
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*first try with info 1*/
- hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 1, &ctr);
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- /*then we buffer the SAM_UNK_INFO_1 structure*/
- info1 = ctr.info.inf1;
- }
- else {
- /*then the call failed, store the status and ZERO out the info structure*/
- ZERO_STRUCT(info1);
- status_buf = hnd->status;
- fail_count++;
- }
-
- /*try again for the next one*/
- hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 2, &ctr);
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- /*store the info*/
- info2 = ctr.info.inf2;
- }
- else {
- /*ZERO out the structure and store the bad status*/
- ZERO_STRUCT(info2);
- status_buf = hnd->status;
- fail_count++;
- }
-
- /*once more*/
- hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 12, &ctr);
-
- if(NT_STATUS_IS_OK(hnd->status)) {
- info12 = ctr.info.inf12;
- }
- else {
- ZERO_STRUCT(info12);
- status_buf = hnd->status;
- fail_count++;
- }
-
- /*return failure if all 3 calls failed*/
- if(fail_count == 3)
- return CAC_FAILURE;
-
- op->out.info = cac_MakeDomainInfo(mem_ctx, &info1, &info2, &info12);
-
- if(!op->out.info) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- if(fail_count > 0) {
- hnd->status = status_buf;
- return CAC_PARTIAL_SUCCESS;
- }
-
- return CAC_SUCCESS;
}
-int cac_SamGetDomainInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfoCtr *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- SAM_UNK_CTR *ctr_out;
+int cac_SamSetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamSetAliasInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ ALIAS_INFO_CTR *ctr = NULL;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- ctr_out = talloc(mem_ctx, SAM_UNK_CTR);
- if(!ctr_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
+ if ( !ctr ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.info_class, ctr_out);
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ hnd->status =
+ rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
+ op->in.alias_hnd, ctr );
- op->out.info = ctr_out;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetDisplayInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDisplayInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- SAM_DISPINFO_CTR ctr_out;
-
- uint32 max_entries_buf = 0;
- uint32 max_size_buf = 0;
-
- uint32 resume_idx_out;
- uint32 num_entries_out;
+int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetDomainInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ SAM_UNK_CTR ctr;
+ SAM_UNK_INFO_1 info1;
+ SAM_UNK_INFO_2 info2;
+ SAM_UNK_INFO_12 info12;
+
+ /*use this to keep track of a failed call */
+ NTSTATUS status_buf = NT_STATUS_OK;
+
+ uint16 fail_count = 0;
+
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*first try with info 1 */
+ hnd->status =
+ rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ 1, &ctr );
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ /*then we buffer the SAM_UNK_INFO_1 structure */
+ info1 = ctr.info.inf1;
+ } else {
+ /*then the call failed, store the status and ZERO out the info structure */
+ ZERO_STRUCT( info1 );
+ status_buf = hnd->status;
+ fail_count++;
+ }
+
+ /*try again for the next one */
+ hnd->status =
+ rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ 2, &ctr );
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ /*store the info */
+ info2 = ctr.info.inf2;
+ } else {
+ /*ZERO out the structure and store the bad status */
+ ZERO_STRUCT( info2 );
+ status_buf = hnd->status;
+ fail_count++;
+ }
+
+ /*once more */
+ hnd->status =
+ rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ 12, &ctr );
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ info12 = ctr.info.inf12;
+ } else {
+ ZERO_STRUCT( info12 );
+ status_buf = hnd->status;
+ fail_count++;
+ }
+
+ /*return failure if all 3 calls failed */
+ if ( fail_count == 3 )
+ return CAC_FAILURE;
+
+ op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
+
+ if ( !op->out.info ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ if ( fail_count > 0 ) {
+ hnd->status = status_buf;
+ return CAC_PARTIAL_SUCCESS;
+ }
+
+ return CAC_SUCCESS;
+}
- if(!hnd)
- return CAC_FAILURE;
+int cac_SamGetDomainInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetDomainInfoCtr *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ SAM_UNK_CTR *ctr_out;
- if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- if(op->out.done == True) /*this is done so we can use the function as a loop condition*/
- return CAC_FAILURE;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(op->in.max_entries == 0 || op->in.max_size == 0) {
- get_query_dispinfo_params(op->out.loop_count, &max_entries_buf, &max_size_buf);
- }
- else {
- max_entries_buf = op->in.max_entries;
- max_size_buf = op->in.max_size;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- resume_idx_out = op->out.resume_idx;
+ ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
+ if ( !ctr_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.info_class,
- &num_entries_out, max_entries_buf, max_size_buf, &ctr_out);
+ hnd->status =
+ rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ op->in.info_class, ctr_out );
- if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_MORE_ENTRIES)) {
- /*be defensive, maybe they'll call again without zeroing the struct*/
- op->out.loop_count = 0;
- op->out.resume_idx = 0;
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(NT_STATUS_IS_OK(hnd->status)) {
- /*we want to quit once the function is called next. so it can be used in a loop*/
- op->out.done = True;
- }
+ op->out.info = ctr_out;
- op->out.resume_idx = resume_idx_out;
- op->out.num_entries = num_entries_out;
- op->out.ctr = ctr_out;
- op->out.loop_count++;
+ return CAC_SUCCESS;
+}
- return CAC_SUCCESS;
+int cac_SamGetDisplayInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetDisplayInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ SAM_DISPINFO_CTR ctr_out;
+
+ uint32 max_entries_buf = 0;
+ uint32 max_size_buf = 0;
+
+ uint32 resume_idx_out;
+ uint32 num_entries_out;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ if ( op->out.done == True ) /*this is done so we can use the function as a loop condition */
+ return CAC_FAILURE;
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( op->in.max_entries == 0 || op->in.max_size == 0 ) {
+ get_query_dispinfo_params( op->out.loop_count,
+ &max_entries_buf, &max_size_buf );
+ } else {
+ max_entries_buf = op->in.max_entries;
+ max_size_buf = op->in.max_size;
+ }
+
+ resume_idx_out = op->out.resume_idx;
+
+ hnd->status =
+ rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd,
+ &resume_idx_out,
+ op->in.info_class,
+ &num_entries_out, max_entries_buf,
+ max_size_buf, &ctr_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status )
+ && !NT_STATUS_EQUAL( hnd->status, STATUS_MORE_ENTRIES ) ) {
+ /*be defensive, maybe they'll call again without zeroing the struct */
+ op->out.loop_count = 0;
+ op->out.resume_idx = 0;
+ return CAC_FAILURE;
+ }
+
+ if ( NT_STATUS_IS_OK( hnd->status ) ) {
+ /*we want to quit once the function is called next. so it can be used in a loop */
+ op->out.done = True;
+ }
+
+ op->out.resume_idx = resume_idx_out;
+ op->out.num_entries = num_entries_out;
+ op->out.ctr = ctr_out;
+ op->out.loop_count++;
+
+ return CAC_SUCCESS;
}
-int cac_SamLookupDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamLookupDomain *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamLookupDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamLookupDomain *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ DOM_SID *sid_out = NULL;
- DOM_SID *sid_out = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.sam || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.sam || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- sid_out = talloc(mem_ctx, DOM_SID);
- if(!sid_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ sid_out = talloc( mem_ctx, DOM_SID );
+ if ( !sid_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam, op->in.name, sid_out);
+ hnd->status =
+ rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam,
+ op->in.name, sid_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.sid = sid_out;
+ op->out.sid = sid_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetSecurityObject *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_SamGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamGetSecurityObject *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level*/
- uint32 sec_info = DACL_SECURITY_INFORMATION;
+ /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level */
+ uint32 sec_info = DACL_SECURITY_INFORMATION;
- SEC_DESC_BUF *sec_out = NULL;
+ SEC_DESC_BUF *sec_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op->in.pol || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.pol || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_samr_query_sec_obj(pipe_hnd, mem_ctx, op->in.pol, sec_info, mem_ctx, &sec_out);
+ hnd->status =
+ rpccli_samr_query_sec_obj( pipe_hnd, mem_ctx, op->in.pol,
+ sec_info, mem_ctx, &sec_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.sec = sec_out;
+ op->out.sec = sec_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op) {
- struct SamOpenDomain od;
+int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SamFlush *op )
+{
+ struct SamOpenDomain od;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.dom_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.dom_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!cac_SamClose(hnd, mem_ctx, op->in.dom_hnd))
- return CAC_FAILURE;
+ if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
+ return CAC_FAILURE;
- ZERO_STRUCT(od);
- od.in.access = (op->in.access) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
- od.in.sid = op->in.sid;
+ ZERO_STRUCT( od );
+ od.in.access =
+ ( op->in.access ) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
+ od.in.sid = op->in.sid;
- if(!cac_SamOpenDomain(hnd, mem_ctx, &od))
- return CAC_FAILURE;
+ if ( !cac_SamOpenDomain( hnd, mem_ctx, &od ) )
+ return CAC_FAILURE;
- /*this function does not use an output parameter to make it as convenient as possible to use*/
- *op->in.dom_hnd = *od.out.dom_hnd;
+ /*this function does not use an output parameter to make it as convenient as possible to use */
+ *op->in.dom_hnd = *od.out.dom_hnd;
- TALLOC_FREE(od.out.dom_hnd);
+ TALLOC_FREE( od.out.dom_hnd );
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
diff --git a/source/libmsrpc/cac_svcctl.c b/source/libmsrpc/cac_svcctl.c
index 83dc0364930..3d3034df15c 100644
--- a/source/libmsrpc/cac_svcctl.c
+++ b/source/libmsrpc/cac_svcctl.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation (SVCCTL pipe)
@@ -23,259 +24,292 @@
#define WAIT_SLEEP_TIME 300000
-int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
-
- POLICY_HND *scm_out = NULL;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || op->in.access == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
-
- /*initialize for samr pipe if we have to*/
- if(!hnd->_internal.pipes[PI_SVCCTL]) {
- if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SVCCTL, &(hnd->status)))) {
- hnd->status = NT_STATUS_UNSUCCESSFUL;
- return CAC_FAILURE;
- }
-
- hnd->_internal.pipes[PI_SVCCTL] = True;
- }
-
- scm_out = talloc(mem_ctx, POLICY_HND);
- if(!scm_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out, op->in.access);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- op->out.scm_hnd = scm_out;
-
- return CAC_SUCCESS;
+int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
+ SERVICE_STATUS * status );
+
+int cac_SvcOpenScm( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcOpenScm *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ POLICY_HND *scm_out = NULL;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || op->in.access == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ /*initialize for samr pipe if we have to */
+ if ( !hnd->_internal.pipes[PI_SVCCTL] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_SVCCTL,
+ &( hnd->status ) ) ) ) {
+ hnd->status = NT_STATUS_UNSUCCESSFUL;
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_SVCCTL] = True;
+ }
+
+ scm_out = talloc( mem_ctx, POLICY_HND );
+ if ( !scm_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out,
+ op->in.access );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->out.scm_hnd = scm_out;
+
+ return CAC_SUCCESS;
}
-int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * scm_hnd )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!scm_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !scm_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcEnumServices( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcEnumServices *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- uint32 type_buf = 0;
- uint32 state_buf = 0;
+ uint32 type_buf = 0;
+ uint32 state_buf = 0;
- uint32 num_svc_out = 0;
+ uint32 num_svc_out = 0;
- ENUM_SERVICES_STATUS *svc_buf = NULL;
+ ENUM_SERVICES_STATUS *svc_buf = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.scm_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.scm_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- type_buf = (op->in.type != 0) ? op->in.type : (SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32);
- state_buf = (op->in.state != 0) ? op->in.state : SVCCTL_STATE_ALL;
+ type_buf =
+ ( op->in.type !=
+ 0 ) ? op->in.
+ type : ( SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32 );
+ state_buf = ( op->in.state != 0 ) ? op->in.state : SVCCTL_STATE_ALL;
- err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx, op->in.scm_hnd, type_buf, state_buf, &num_svc_out, &svc_buf);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx,
+ op->in.scm_hnd, type_buf,
+ state_buf, &num_svc_out,
+ &svc_buf );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.services = cac_MakeServiceArray(mem_ctx, svc_buf, num_svc_out);
+ op->out.services =
+ cac_MakeServiceArray( mem_ctx, svc_buf, num_svc_out );
- if(!op->out.services) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ if ( !op->out.services ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- TALLOC_FREE(svc_buf);
+ TALLOC_FREE( svc_buf );
- op->out.num_services = num_svc_out;
+ op->out.num_services = num_svc_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcOpenService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcOpenService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- POLICY_HND *svc_hnd_out = NULL;
+ POLICY_HND *svc_hnd_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.scm_hnd || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.scm_hnd || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- svc_hnd_out = talloc(mem_ctx, POLICY_HND);
- if(!svc_hnd_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ svc_hnd_out = talloc( mem_ctx, POLICY_HND );
+ if ( !svc_hnd_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd, svc_hnd_out, op->in.name, op->in.access);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd,
+ svc_hnd_out, op->in.name,
+ op->in.access );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.svc_hnd = svc_hnd_out;
+ op->out.svc_hnd = svc_hnd_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcControlService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcControlService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_out;
+ SERVICE_STATUS status_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(op->in.control < SVCCTL_CONTROL_STOP || op->in.control > SVCCTL_CONTROL_SHUTDOWN) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( op->in.control < SVCCTL_CONTROL_STOP
+ || op->in.control > SVCCTL_CONTROL_SHUTDOWN ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, op->in.control, &status_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
+ op->in.svc_hnd, op->in.control,
+ &status_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcGetStatus( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcGetStatus *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_out;
+ SERVICE_STATUS status_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd, &status_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd,
+ &status_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.status = status_out;
+ op->out.status = status_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
@@ -288,273 +322,313 @@ int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetSta
* returns CAC_FAILURE if the state is never reached
* or CAC_SUCCESS if the state is reached
*/
-int cac_WaitForService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *svc_hnd, uint32 state, uint32 timeout, SERVICE_STATUS *status) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- /*number of milliseconds we have spent*/
- uint32 time_spent = 0;
- WERROR err;
-
- if(!hnd || !mem_ctx || !svc_hnd || !status)
- return CAC_FAILURE;
-
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- while(status->state != state && time_spent < (timeout * 1000000) && NT_STATUS_IS_OK(hnd->status)) {
- /*if this is the first call, then we _just_ got the status.. sleep now*/
- usleep(WAIT_SLEEP_TIME);
- time_spent += WAIT_SLEEP_TIME;
-
- err = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, svc_hnd, status);
- hnd->status = werror_to_ntstatus(err);
- }
-
- if(status->state == state)
- return CAC_SUCCESS;
-
- return CAC_FAILURE;
+int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
+ SERVICE_STATUS * status )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ /*number of milliseconds we have spent */
+ uint32 time_spent = 0;
+ WERROR err;
+
+ if ( !hnd || !mem_ctx || !svc_hnd || !status )
+ return CAC_FAILURE;
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ while ( status->state != state && time_spent < ( timeout * 1000000 )
+ && NT_STATUS_IS_OK( hnd->status ) ) {
+ /*if this is the first call, then we _just_ got the status.. sleep now */
+ usleep( WAIT_SLEEP_TIME );
+ time_spent += WAIT_SLEEP_TIME;
+
+ err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, svc_hnd,
+ status );
+ hnd->status = werror_to_ntstatus( err );
+ }
+
+ if ( status->state == state )
+ return CAC_SUCCESS;
+
+ return CAC_FAILURE;
}
-int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcStartService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcStartService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_buf;
+ SERVICE_STATUS status_buf;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(op->in.num_parms != 0 && op->in.parms == NULL) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( op->in.num_parms != 0 && op->in.parms == NULL ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, op->in.svc_hnd, (const char **)op->in.parms, op->in.num_parms);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_start_service( pipe_hnd, mem_ctx, op->in.svc_hnd,
+ ( const char ** ) op->in.parms,
+ op->in.num_parms );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(op->in.timeout == 0)
- return CAC_SUCCESS;
+ if ( op->in.timeout == 0 )
+ return CAC_SUCCESS;
- return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &status_buf);
+ return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
+ SVCCTL_RUNNING, op->in.timeout,
+ &status_buf );
}
-int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcStopService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcStopService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_out;
+ SERVICE_STATUS status_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_STOP, &status_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
+ op->in.svc_hnd,
+ SVCCTL_CONTROL_STOP,
+ &status_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.status = status_out;
+ op->out.status = status_out;
- if(op->in.timeout == 0)
- return CAC_SUCCESS;
+ if ( op->in.timeout == 0 )
+ return CAC_SUCCESS;
- return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_STOPPED, op->in.timeout, &op->out.status);
+ return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
+ SVCCTL_STOPPED, op->in.timeout,
+ &op->out.status );
}
-int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcPauseService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcPauseService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_out;
+ SERVICE_STATUS status_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_PAUSE, &status_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
+ op->in.svc_hnd,
+ SVCCTL_CONTROL_PAUSE,
+ &status_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.status = status_out;
+ op->out.status = status_out;
- if(op->in.timeout == 0)
- return CAC_SUCCESS;
+ if ( op->in.timeout == 0 )
+ return CAC_SUCCESS;
- return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_PAUSED, op->in.timeout, &op->out.status);
+ return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
+ SVCCTL_PAUSED, op->in.timeout,
+ &op->out.status );
}
-int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcContinueService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcContinueService *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- SERVICE_STATUS status_out;
+ SERVICE_STATUS status_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_CONTINUE, &status_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
+ op->in.svc_hnd,
+ SVCCTL_CONTROL_CONTINUE,
+ &status_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.status = status_out;
+ op->out.status = status_out;
- if(op->in.timeout == 0)
- return CAC_SUCCESS;
+ if ( op->in.timeout == 0 )
+ return CAC_SUCCESS;
- return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &op->out.status);
+ return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
+ SVCCTL_RUNNING, op->in.timeout,
+ &op->out.status );
}
-int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcGetDisplayName( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcGetDisplayName *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- fstring disp_name_out;
+ fstring disp_name_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd, disp_name_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd,
+ disp_name_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.display_name = talloc_strdup(mem_ctx, disp_name_out);
+ op->out.display_name = talloc_strdup( mem_ctx, disp_name_out );
- if(!op->out.display_name) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ if ( !op->out.display_name ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_SvcGetServiceConfig( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct SvcGetServiceConfig *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ SERVICE_CONFIG config_out;
- SERVICE_CONFIG config_out;
-
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.svc_hnd || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.svc_hnd || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd, &config_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd,
+ &config_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ if ( !cac_InitCacServiceConfig
+ ( mem_ctx, &config_out, &op->out.config ) ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
diff --git a/source/libmsrpc/cac_winreg.c b/source/libmsrpc/cac_winreg.c
index 6ef898eb16d..1546cfeda4c 100644
--- a/source/libmsrpc/cac_winreg.c
+++ b/source/libmsrpc/cac_winreg.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation (WINREG pipe)
@@ -21,1007 +22,1101 @@
#include "libmsrpc.h"
#include "libmsrpc_internal.h"
-
-int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
- POLICY_HND *key = NULL;
- WERROR err;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.root || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
-
- /*initialize for winreg pipe if we have to*/
- if(!hnd->_internal.pipes[PI_WINREG]) {
- if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_WINREG, &(hnd->status)))) {
- return CAC_FAILURE;
- }
-
- hnd->_internal.pipes[PI_WINREG] = True;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- key = talloc(mem_ctx, POLICY_HND);
- if(!key) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- err = rpccli_reg_connect( pipe_hnd, mem_ctx, op->in.root, op->in.access, key);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- op->out.key = key;
-
- return CAC_SUCCESS;
+WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
+ TALLOC_CTX * mem_ctx, POLICY_HND * key );
+
+int cac_RegConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegConnect *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND *key = NULL;
+ WERROR err;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.root || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return CAC_FAILURE;
+ }
+
+ /*initialize for winreg pipe if we have to */
+ if ( !hnd->_internal.pipes[PI_WINREG] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_WINREG,
+ &( hnd->status ) ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_WINREG] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ key = talloc( mem_ctx, POLICY_HND );
+ if ( !key ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ err = rpccli_reg_connect( pipe_hnd, mem_ctx, op->in.root,
+ op->in.access, key );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.key = key;
+
+ return CAC_SUCCESS;
}
-int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * key )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!key || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !key || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_close(pipe_hnd, mem_ctx, key);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_close( pipe_hnd, mem_ctx, key );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegOpenKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegOpenKey *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegOpenKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- POLICY_HND *key_out;
- POLICY_HND *parent_key;
+ POLICY_HND *key_out;
+ POLICY_HND *parent_key;
- char *key_name = NULL;
- uint32 reg_type = 0;
+ char *key_name = NULL;
+ uint32 reg_type = 0;
- struct RegConnect rc;
+ struct RegConnect rc;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- key_out = talloc(mem_ctx, POLICY_HND);
- if(!key_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ key_out = talloc( mem_ctx, POLICY_HND );
+ if ( !key_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- if(!op->in.parent_key) {
- /*then we need to connect to the registry*/
- if(!cac_ParseRegPath(op->in.name, &reg_type, &key_name)) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op->in.parent_key ) {
+ /*then we need to connect to the registry */
+ if ( !cac_ParseRegPath( op->in.name, &reg_type, &key_name ) ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- /*use cac_RegConnect because it handles the session setup*/
- ZERO_STRUCT(rc);
+ /*use cac_RegConnect because it handles the session setup */
+ ZERO_STRUCT( rc );
- rc.in.access = op->in.access;
- rc.in.root = reg_type;
+ rc.in.access = op->in.access;
+ rc.in.root = reg_type;
- if(!cac_RegConnect(hnd, mem_ctx, &rc)) {
- return CAC_FAILURE;
- }
+ if ( !cac_RegConnect( hnd, mem_ctx, &rc ) ) {
+ return CAC_FAILURE;
+ }
/**if they only specified the root key, return the key we just opened*/
- if(key_name == NULL) {
- op->out.key = rc.out.key;
- return CAC_SUCCESS;
- }
-
- parent_key = rc.out.key;
- }
- else {
- parent_key = op->in.parent_key;
- key_name = op->in.name;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, parent_key, key_name, op->in.access, key_out);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- if(!op->in.parent_key) {
- /*then close the one that we opened above*/
- err = rpccli_reg_close( pipe_hnd, mem_ctx, parent_key);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
- }
-
- op->out.key = key_out;
-
- return CAC_SUCCESS;
+ if ( key_name == NULL ) {
+ op->out.key = rc.out.key;
+ return CAC_SUCCESS;
+ }
+
+ parent_key = rc.out.key;
+ } else {
+ parent_key = op->in.parent_key;
+ key_name = op->in.name;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, parent_key, key_name,
+ op->in.access, key_out );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.parent_key ) {
+ /*then close the one that we opened above */
+ err = rpccli_reg_close( pipe_hnd, mem_ctx, parent_key );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+ }
+
+ op->out.key = key_out;
+
+ return CAC_SUCCESS;
}
-int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKeys *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
-
- /*buffers for rpccli_reg_enum_key call*/
- fstring key_name_in;
- fstring class_name_in;
-
- /*output buffers*/
- char **key_names_out = NULL;
- char **class_names_out = NULL;
- time_t *mod_times_out = NULL;
- uint32 num_keys_out = 0;
- uint32 resume_idx = 0;
-
- if(!hnd)
- return CAC_FAILURE;
-
- /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
- if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED))
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || op->in.max_keys == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+int cac_RegEnumKeys( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegEnumKeys *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ /*buffers for rpccli_reg_enum_key call */
+ fstring key_name_in;
+ fstring class_name_in;
+
+ /*output buffers */
+ char **key_names_out = NULL;
+ char **class_names_out = NULL;
+ time_t *mod_times_out = NULL;
+ uint32 num_keys_out = 0;
+ uint32 resume_idx = 0;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again */
+ if ( NT_STATUS_V( hnd->status ) ==
+ NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || op->in.max_keys == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
/**the only way to know how many keys to expect is to assume max_keys keys will be found*/
- key_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys);
- if(!key_names_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- class_names_out = TALLOC_ARRAY(mem_ctx, char *, op->in.max_keys);
- if(!class_names_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(key_names_out);
- return CAC_FAILURE;
- }
-
- mod_times_out = TALLOC_ARRAY(mem_ctx, time_t, op->in.max_keys);
- if(!mod_times_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(key_names_out);
- TALLOC_FREE(class_names_out);
-
- return CAC_FAILURE;
- }
-
- resume_idx = op->out.resume_idx;
-
- do {
- err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, op->in.key, resume_idx, key_name_in, class_name_in, &mod_times_out[num_keys_out]);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- /*don't increment any values*/
- break;
- }
-
- key_names_out[num_keys_out] = talloc_strdup(mem_ctx, key_name_in);
-
- class_names_out[num_keys_out] = talloc_strdup(mem_ctx, class_name_in);
-
- if(!key_names_out[num_keys_out] || !class_names_out[num_keys_out]) {
- hnd->status = NT_STATUS_NO_MEMORY;
- break;
- }
-
- resume_idx++;
- num_keys_out++;
- } while(num_keys_out < op->in.max_keys);
-
- if(CAC_OP_FAILED(hnd->status)) {
- op->out.num_keys = 0;
- return CAC_FAILURE;
- }
-
- op->out.resume_idx = resume_idx;
- op->out.num_keys = num_keys_out;
- op->out.key_names = key_names_out;
- op->out.class_names = class_names_out;
- op->out.mod_times = mod_times_out;
-
- return CAC_SUCCESS;
+ key_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
+ if ( !key_names_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ class_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
+ if ( !class_names_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( key_names_out );
+ return CAC_FAILURE;
+ }
+
+ mod_times_out = TALLOC_ARRAY( mem_ctx, time_t, op->in.max_keys );
+ if ( !mod_times_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ TALLOC_FREE( key_names_out );
+ TALLOC_FREE( class_names_out );
+
+ return CAC_FAILURE;
+ }
+
+ resume_idx = op->out.resume_idx;
+
+ do {
+ err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, op->in.key,
+ resume_idx, key_name_in,
+ class_name_in,
+ &mod_times_out[num_keys_out] );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ /*don't increment any values */
+ break;
+ }
+
+ key_names_out[num_keys_out] =
+ talloc_strdup( mem_ctx, key_name_in );
+
+ class_names_out[num_keys_out] =
+ talloc_strdup( mem_ctx, class_name_in );
+
+ if ( !key_names_out[num_keys_out]
+ || !class_names_out[num_keys_out] ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ break;
+ }
+
+ resume_idx++;
+ num_keys_out++;
+ } while ( num_keys_out < op->in.max_keys );
+
+ if ( CAC_OP_FAILED( hnd->status ) ) {
+ op->out.num_keys = 0;
+ return CAC_FAILURE;
+ }
+
+ op->out.resume_idx = resume_idx;
+ op->out.num_keys = num_keys_out;
+ op->out.key_names = key_names_out;
+ op->out.class_names = class_names_out;
+ op->out.mod_times = mod_times_out;
+
+ return CAC_SUCCESS;
}
-int cac_RegCreateKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegCreateKey *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegCreateKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegCreateKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- POLICY_HND *key_out;
+ POLICY_HND *key_out;
- struct RegOpenKey rok;
+ struct RegOpenKey rok;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.parent_key || !op->in.key_name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.parent_key || !op->in.key_name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
- ZERO_STRUCT(rok);
+ /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
+ ZERO_STRUCT( rok );
- rok.in.name = op->in.key_name;
- rok.in.access = op->in.access;
- rok.in.parent_key = op->in.parent_key;
+ rok.in.name = op->in.key_name;
+ rok.in.access = op->in.access;
+ rok.in.parent_key = op->in.parent_key;
- if(cac_RegOpenKey(hnd, mem_ctx, &rok)) {
- /*then we got the key, return*/
- op->out.key = rok.out.key;
- return CAC_SUCCESS;
- }
+ if ( cac_RegOpenKey( hnd, mem_ctx, &rok ) ) {
+ /*then we got the key, return */
+ op->out.key = rok.out.key;
+ return CAC_SUCCESS;
+ }
- /*just be ultra-safe*/
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ /*just be ultra-safe */
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- key_out = talloc(mem_ctx, POLICY_HND);
- if(!key_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ key_out = talloc( mem_ctx, POLICY_HND );
+ if ( !key_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_create_key_ex( pipe_hnd, mem_ctx, op->in.parent_key, op->in.key_name, op->in.class_name, op->in.access, key_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_create_key_ex( pipe_hnd, mem_ctx, op->in.parent_key,
+ op->in.key_name, op->in.class_name,
+ op->in.access, key_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- op->out.key = key_out;
+ op->out.key = key_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-WERROR cac_delete_subkeys_recursive(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
- /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
- * so we use the cli_reg functions directly*/
+WERROR cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
+ TALLOC_CTX * mem_ctx, POLICY_HND * key )
+{
+ /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
+ * so we use the cli_reg functions directly*/
- WERROR err = WERR_OK;
+ WERROR err = WERR_OK;
- POLICY_HND subkey;
- fstring subkey_name;
- fstring class_buf;
- time_t mod_time_buf;
+ POLICY_HND subkey;
+ fstring subkey_name;
+ fstring class_buf;
+ time_t mod_time_buf;
- int cur_key = 0;
+ int cur_key = 0;
- while(W_ERROR_IS_OK(err)) {
- err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, key, cur_key, subkey_name, class_buf, &mod_time_buf);
+ while ( W_ERROR_IS_OK( err ) ) {
+ err = rpccli_reg_enum_key( pipe_hnd, mem_ctx, key, cur_key,
+ subkey_name, class_buf,
+ &mod_time_buf );
- if(!W_ERROR_IS_OK(err))
- break;
+ if ( !W_ERROR_IS_OK( err ) )
+ break;
- /*try to open the key with full access*/
- err = rpccli_reg_open_entry(pipe_hnd, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey);
+ /*try to open the key with full access */
+ err = rpccli_reg_open_entry( pipe_hnd, mem_ctx, key,
+ subkey_name, REG_KEY_ALL,
+ &subkey );
- if(!W_ERROR_IS_OK(err))
- break;
+ if ( !W_ERROR_IS_OK( err ) )
+ break;
- err = cac_delete_subkeys_recursive(pipe_hnd, mem_ctx, &subkey);
+ err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
+ &subkey );
- if(!W_ERROR_EQUAL(err,WERR_NO_MORE_ITEMS) && !W_ERROR_IS_OK(err))
- break;
+ if ( !W_ERROR_EQUAL( err, WERR_NO_MORE_ITEMS )
+ && !W_ERROR_IS_OK( err ) )
+ break;
- /*flush the key just to be safe*/
- rpccli_reg_flush_key(pipe_hnd, mem_ctx, key);
-
- /*close the key that we opened*/
- rpccli_reg_close(pipe_hnd, mem_ctx, &subkey);
+ /*flush the key just to be safe */
+ rpccli_reg_flush_key( pipe_hnd, mem_ctx, key );
- /*now we delete the subkey*/
- err = rpccli_reg_delete_key(pipe_hnd, mem_ctx, key, subkey_name);
+ /*close the key that we opened */
+ rpccli_reg_close( pipe_hnd, mem_ctx, &subkey );
+ /*now we delete the subkey */
+ err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, key,
+ subkey_name );
- cur_key++;
- }
+ cur_key++;
+ }
- return err;
+
+ return err;
}
-int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegDeleteKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( op->in.recursive ) {
+ /*first open the key, and then delete all of it's subkeys recursively */
+ struct RegOpenKey rok;
- if(op->in.recursive) {
- /*first open the key, and then delete all of it's subkeys recursively*/
- struct RegOpenKey rok;
- ZERO_STRUCT(rok);
+ ZERO_STRUCT( rok );
- rok.in.parent_key = op->in.parent_key;
- rok.in.name = op->in.name;
- rok.in.access = REG_KEY_ALL;
+ rok.in.parent_key = op->in.parent_key;
+ rok.in.name = op->in.name;
+ rok.in.access = REG_KEY_ALL;
- if(!cac_RegOpenKey(hnd, mem_ctx, &rok))
- return CAC_FAILURE;
+ if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
+ return CAC_FAILURE;
- err = cac_delete_subkeys_recursive(pipe_hnd, mem_ctx, rok.out.key);
+ err = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
+ rok.out.key );
- /*close the key that we opened*/
- cac_RegClose(hnd, mem_ctx, rok.out.key);
+ /*close the key that we opened */
+ cac_RegClose( hnd, mem_ctx, rok.out.key );
- hnd->status = werror_to_ntstatus(err);
+ hnd->status = werror_to_ntstatus( err );
- if(NT_STATUS_V(hnd->status) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED) && !NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( NT_STATUS_V( hnd->status ) !=
+ NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
+ && !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- /*now go on to actually delete the key*/
- }
+ /*now go on to actually delete the key */
+ }
- err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, op->in.parent_key, op->in.name);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_delete_key( pipe_hnd, mem_ctx, op->in.parent_key,
+ op->in.name );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegDeleteValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_delete_val( pipe_hnd, mem_ctx, op->in.parent_key, op->in.name);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_delete_val( pipe_hnd, mem_ctx, op->in.parent_key,
+ op->in.name );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
#if 0
+
/* JRA - disabled until fix. */
+
/* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
cleanly and resubmit the query. */
-int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
-
- char *class_name_out = NULL;
- uint32 class_len = 0;
- uint32 num_subkeys_out = 0;
- uint32 long_subkey_out = 0;
- uint32 long_class_out = 0;
- uint32 num_values_out = 0;
- uint32 long_value_out = 0;
- uint32 long_data_out = 0;
- uint32 secdesc_size = 0;
- NTTIME mod_time;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.key || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
- class_name_out,
- &class_len,
- &num_subkeys_out,
- &long_subkey_out,
- &long_class_out,
- &num_values_out,
- &long_value_out,
- &long_data_out,
- &secdesc_size,
- &mod_time);
-
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- if(!class_name_out) {
- op->out.class_name = talloc_strdup(mem_ctx, "");
- }
- else if(class_len != 0 && class_name_out[class_len - 1] != '\0') {
- /*then we need to add a '\0'*/
- op->out.class_name = talloc_size(mem_ctx, sizeof(char)*(class_len + 1));
-
- memcpy(op->out.class_name, class_name_out, class_len);
-
- op->out.class_name[class_len] = '\0';
- }
- else { /*then everything worked out fine in the function*/
- op->out.class_name = talloc_strdup(mem_ctx, class_name_out);
- }
-
- if(!op->out.class_name) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- op->out.num_subkeys = num_subkeys_out;
- op->out.longest_subkey = long_subkey_out;
- op->out.longest_class = long_class_out;
- op->out.num_values = num_values_out;
- op->out.longest_value_name = long_value_out;
- op->out.longest_value_data = long_data_out;
- op->out.security_desc_size = secdesc_size;
- op->out.last_write_time = nt_time_to_unix(&mod_time);
-
- return CAC_FAILURE;
+int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegQueryKeyInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ char *class_name_out = NULL;
+ uint32 class_len = 0;
+ uint32 num_subkeys_out = 0;
+ uint32 long_subkey_out = 0;
+ uint32 long_class_out = 0;
+ uint32 num_values_out = 0;
+ uint32 long_value_out = 0;
+ uint32 long_data_out = 0;
+ uint32 secdesc_size = 0;
+ NTTIME mod_time;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.key || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
+ class_name_out,
+ &class_len,
+ &num_subkeys_out,
+ &long_subkey_out,
+ &long_class_out,
+ &num_values_out,
+ &long_value_out,
+ &long_data_out,
+ &secdesc_size, &mod_time );
+
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ if ( !class_name_out ) {
+ op->out.class_name = talloc_strdup( mem_ctx, "" );
+ } else if ( class_len != 0 && class_name_out[class_len - 1] != '\0' ) {
+ /*then we need to add a '\0' */
+ op->out.class_name =
+ talloc_size( mem_ctx,
+ sizeof( char ) * ( class_len + 1 ) );
+
+ memcpy( op->out.class_name, class_name_out, class_len );
+
+ op->out.class_name[class_len] = '\0';
+ } else { /*then everything worked out fine in the function */
+ op->out.class_name = talloc_strdup( mem_ctx, class_name_out );
+ }
+
+ if ( !op->out.class_name ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ op->out.num_subkeys = num_subkeys_out;
+ op->out.longest_subkey = long_subkey_out;
+ op->out.longest_class = long_class_out;
+ op->out.num_values = num_values_out;
+ op->out.longest_value_name = long_value_out;
+ op->out.longest_value_data = long_data_out;
+ op->out.security_desc_size = secdesc_size;
+ op->out.last_write_time = nt_time_to_unix( &mod_time );
+
+ return CAC_FAILURE;
}
#endif
-int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegQueryValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- uint32 val_type;
- REGVAL_BUFFER buffer;
- REG_VALUE_DATA *data_out = NULL;
+ uint32 val_type;
+ REGVAL_BUFFER buffer;
+ REG_VALUE_DATA *data_out = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_query_value(pipe_hnd, mem_ctx, op->in.key, op->in.val_name, &val_type, &buffer);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_query_value( pipe_hnd, mem_ctx, op->in.key,
+ op->in.val_name, &val_type, &buffer );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- data_out = cac_MakeRegValueData(mem_ctx, val_type, buffer);
- if(!data_out) {
- if(errno == ENOMEM)
- hnd->status = NT_STATUS_NO_MEMORY;
- else
- hnd->status = NT_STATUS_INVALID_PARAMETER;
+ data_out = cac_MakeRegValueData( mem_ctx, val_type, buffer );
+ if ( !data_out ) {
+ if ( errno == ENOMEM )
+ hnd->status = NT_STATUS_NO_MEMORY;
+ else
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ return CAC_FAILURE;
+ }
- op->out.type = val_type;
- op->out.data = data_out;
+ op->out.type = val_type;
+ op->out.data = data_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumValues *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
-
- /*buffers for rpccli_reg_enum_key call*/
- fstring val_name_buf;
- REGVAL_BUFFER val_buf;
-
- /*output buffers*/
- uint32 *types_out = NULL;
- REG_VALUE_DATA **values_out = NULL;
- char **val_names_out = NULL;
- uint32 num_values_out = 0;
- uint32 resume_idx = 0;
-
- if(!hnd)
- return CAC_FAILURE;
-
- /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
- if(NT_STATUS_V(hnd->status) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED))
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !op->in.key || op->in.max_values == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*we need to assume that the max number of values will be enumerated*/
- types_out = (uint32 *)talloc_array(mem_ctx, int, op->in.max_values);
- if(!types_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values);
- if(!values_out) {
- TALLOC_FREE(types_out);
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- val_names_out = talloc_array(mem_ctx, char *, op->in.max_values);
- if(!val_names_out) {
- TALLOC_FREE(types_out);
- TALLOC_FREE(values_out);
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
-
- resume_idx = op->out.resume_idx;
- do {
- ZERO_STRUCT(val_buf);
-
- err = rpccli_reg_enum_val(pipe_hnd, mem_ctx, op->in.key, resume_idx, val_name_buf, &types_out[num_values_out], &val_buf);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- break;
-
- values_out[num_values_out] = cac_MakeRegValueData(mem_ctx, types_out[num_values_out], val_buf);
- val_names_out[num_values_out] = talloc_strdup(mem_ctx, val_name_buf);
-
- if(!val_names_out[num_values_out] || !values_out[num_values_out]) {
- hnd->status = NT_STATUS_NO_MEMORY;
- break;
- }
-
- num_values_out++;
- resume_idx++;
- } while(num_values_out < op->in.max_values);
-
- if(CAC_OP_FAILED(hnd->status))
- return CAC_FAILURE;
-
- op->out.types = types_out;
- op->out.num_values = num_values_out;
- op->out.value_names = val_names_out;
- op->out.values = values_out;
- op->out.resume_idx = resume_idx;
-
- return CAC_SUCCESS;
+int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegEnumValues *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ /*buffers for rpccli_reg_enum_key call */
+ fstring val_name_buf;
+ REGVAL_BUFFER val_buf;
+
+ /*output buffers */
+ uint32 *types_out = NULL;
+ REG_VALUE_DATA **values_out = NULL;
+ char **val_names_out = NULL;
+ uint32 num_values_out = 0;
+ uint32 resume_idx = 0;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again */
+ if ( NT_STATUS_V( hnd->status ) ==
+ NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*we need to assume that the max number of values will be enumerated */
+ types_out =
+ ( uint32 * ) talloc_array( mem_ctx, int, op->in.max_values );
+ if ( !types_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ values_out =
+ talloc_array( mem_ctx, REG_VALUE_DATA *, op->in.max_values );
+ if ( !values_out ) {
+ TALLOC_FREE( types_out );
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ val_names_out = talloc_array( mem_ctx, char *, op->in.max_values );
+ if ( !val_names_out ) {
+ TALLOC_FREE( types_out );
+ TALLOC_FREE( values_out );
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ resume_idx = op->out.resume_idx;
+ do {
+ ZERO_STRUCT( val_buf );
+
+ err = rpccli_reg_enum_val( pipe_hnd, mem_ctx, op->in.key,
+ resume_idx, val_name_buf,
+ &types_out[num_values_out],
+ &val_buf );
+ hnd->status = werror_to_ntstatus( err );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ break;
+
+ values_out[num_values_out] =
+ cac_MakeRegValueData( mem_ctx,
+ types_out[num_values_out],
+ val_buf );
+ val_names_out[num_values_out] =
+ talloc_strdup( mem_ctx, val_name_buf );
+
+ if ( !val_names_out[num_values_out]
+ || !values_out[num_values_out] ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ break;
+ }
+
+ num_values_out++;
+ resume_idx++;
+ } while ( num_values_out < op->in.max_values );
+
+ if ( CAC_OP_FAILED( hnd->status ) )
+ return CAC_FAILURE;
+
+ op->out.types = types_out;
+ op->out.num_values = num_values_out;
+ op->out.value_names = val_names_out;
+ op->out.values = values_out;
+ op->out.resume_idx = resume_idx;
+
+ return CAC_SUCCESS;
}
-int cac_RegSetValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetValue *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegSetValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
+
+ RPC_DATA_BLOB *buffer;
- RPC_DATA_BLOB *buffer;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
- buffer = cac_MakeRpcDataBlob(mem_ctx, op->in.type, op->in.value);
+ if ( !buffer ) {
+ if ( errno == ENOMEM )
+ hnd->status = NT_STATUS_NO_MEMORY;
+ else
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
- if(!buffer) {
- if(errno == ENOMEM)
- hnd->status = NT_STATUS_NO_MEMORY;
- else
- hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- return CAC_FAILURE;
- }
+ err = rpccli_reg_set_val( pipe_hnd, mem_ctx, op->in.key,
+ op->in.val_name, op->in.type, buffer );
+ hnd->status = werror_to_ntstatus( err );
- err = rpccli_reg_set_val(pipe_hnd, mem_ctx, op->in.key, op->in.val_name, op->in.type, buffer);
- hnd->status = werror_to_ntstatus(err);
-
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- /*flush*/
- err = rpccli_reg_flush_key(pipe_hnd, mem_ctx, op->in.key);
- hnd->status = werror_to_ntstatus(err);
+ /*flush */
+ err = rpccli_reg_flush_key( pipe_hnd, mem_ctx, op->in.key );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegGetVersion *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- uint32 version_out;
+ uint32 version_out;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_getversion( pipe_hnd, mem_ctx, op->in.key, &version_out);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_getversion( pipe_hnd, mem_ctx, op->in.key,
+ &version_out );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.version = version_out;
+ op->out.version = version_out;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetKeySecurity *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegGetKeySecurity *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- uint32 buf_size;
- SEC_DESC_BUF buf;
+ uint32 buf_size;
+ SEC_DESC_BUF buf;
- ZERO_STRUCT(buf);
+ ZERO_STRUCT( buf );
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || op->in.info_type == 0 || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_get_key_sec(pipe_hnd, mem_ctx, op->in.key, op->in.info_type, &buf_size, &buf);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_get_key_sec( pipe_hnd, mem_ctx, op->in.key,
+ op->in.info_type, &buf_size, &buf );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- op->out.size = buf.len;
- op->out.descriptor = dup_sec_desc(mem_ctx, buf.sec);
+ op->out.size = buf.len;
+ op->out.descriptor = dup_sec_desc( mem_ctx, buf.sec );
- if (op->out.descriptor == NULL) {
- return CAC_FAILURE;
- }
+ if ( op->out.descriptor == NULL ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegSetKeySecurity *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || op->in.info_type == 0 || op->in.size == 0 || !op->in.descriptor || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || op->in.info_type == 0 || op->in.size == 0
+ || !op->in.descriptor || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_set_key_sec(pipe_hnd, mem_ctx, op->in.key, op->in.info_type, op->in.size, op->in.descriptor);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_set_key_sec( pipe_hnd, mem_ctx, op->in.key,
+ op->in.info_type, op->in.size,
+ op->in.descriptor );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_RegSaveKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSaveKey *op) {
- struct rpc_pipe_client *pipe_hnd = NULL;
- WERROR err;
+int cac_RegSaveKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegSaveKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ WERROR err;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- if(!op || !op->in.key || !op->in.filename || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || !op->in.filename || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = rpccli_reg_save_key( pipe_hnd, mem_ctx, op->in.key, op->in.filename);
- hnd->status = werror_to_ntstatus(err);
+ err = rpccli_reg_save_key( pipe_hnd, mem_ctx, op->in.key,
+ op->in.filename );
+ hnd->status = werror_to_ntstatus( err );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
-
- char *msg;
-
- if(!hnd)
- return CAC_FAILURE;
-
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- if(!op || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
-
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- /*initialize for winreg pipe if we have to*/
- if(!hnd->_internal.pipes[PI_SHUTDOWN]) {
- if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SHUTDOWN, &(hnd->status)))) {
- return CAC_FAILURE;
- }
-
- hnd->_internal.pipes[PI_SHUTDOWN] = True;
- }
-
- pipe_hnd = cac_GetPipe(hnd, PI_SHUTDOWN);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
-
- msg = (op->in.message != NULL) ? op->in.message : talloc_strdup(mem_ctx, "");
-
- hnd->status = NT_STATUS_OK;
-
- if(hnd->_internal.srv_level > SRV_WIN_NT4) {
- hnd->status = rpccli_shutdown_init_ex( pipe_hnd, mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force, op->in.reason);
- }
-
- if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) {
- hnd->status = rpccli_shutdown_init( pipe_hnd, mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force);
-
- hnd->_internal.srv_level = SRV_WIN_NT4;
- }
-
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct Shutdown *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ char *msg;
+
+ if ( !hnd )
+ return CAC_FAILURE;
+
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ if ( !op || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
+
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*initialize for winreg pipe if we have to */
+ if ( !hnd->_internal.pipes[PI_SHUTDOWN] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_SHUTDOWN,
+ &( hnd->status ) ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_SHUTDOWN] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ msg = ( op->in.message !=
+ NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
+
+ hnd->status = NT_STATUS_OK;
+
+ if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
+ hnd->status =
+ rpccli_shutdown_init_ex( pipe_hnd, mem_ctx, msg,
+ op->in.timeout,
+ op->in.reboot, op->in.force,
+ op->in.reason );
+ }
+
+ if ( hnd->_internal.srv_level < SRV_WIN_2K
+ || !NT_STATUS_IS_OK( hnd->status ) ) {
+ hnd->status =
+ rpccli_shutdown_init( pipe_hnd, mem_ctx, msg,
+ op->in.timeout, op->in.reboot,
+ op->in.force );
+
+ hnd->_internal.srv_level = SRV_WIN_NT4;
+ }
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx) {
- struct rpc_pipe_client *pipe_hnd = NULL;
+int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- pipe_hnd = cac_GetPipe(hnd, PI_SHUTDOWN);
- if(!pipe_hnd) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_SHUTDOWN );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- hnd->status = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
+ hnd->status = rpccli_shutdown_abort( pipe_hnd, mem_ctx );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-
diff --git a/source/libmsrpc/libmsrpc.c b/source/libmsrpc/libmsrpc.c
index 5f71af21da2..0d7bbb8f925 100644
--- a/source/libmsrpc/libmsrpc.c
+++ b/source/libmsrpc/libmsrpc.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation
@@ -23,315 +24,327 @@
#include "libsmbclient.h"
#include "libsmb_internal.h"
+int cac_InitHandleData( CacServerHandle * hnd );
+
/*this function is based on code found in smbc_init_context() (libsmb/libsmbclient.c)*/
-void cac_Init(int debug) {
- if(debug < 0 || debug > 99)
- debug = 0;
+void cac_Init( int debug )
+{
+ if ( debug < 0 || debug > 99 )
+ debug = 0;
- DEBUGLEVEL = debug;
+ DEBUGLEVEL = debug;
- setup_logging("libmsrpc", True);
+ setup_logging( "libmsrpc", True );
}
-int cac_InitHandleMem(CacServerHandle *hnd) {
- hnd->username = SMB_MALLOC_ARRAY(char, sizeof(fstring));
- if(!hnd->username)
- return CAC_FAILURE;
+int cac_InitHandleMem( CacServerHandle * hnd )
+{
+ hnd->username = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
- hnd->username[0] = '\0';
+ if ( !hnd->username )
+ return CAC_FAILURE;
- hnd->domain = SMB_MALLOC_ARRAY(char, sizeof(fstring));
- if(!hnd->domain)
- return CAC_FAILURE;
-
- hnd->domain[0] = '\0';
+ hnd->username[0] = '\0';
- hnd->netbios_name = SMB_MALLOC_ARRAY(char, sizeof(fstring));
- if(!hnd->netbios_name)
- return CAC_FAILURE;
+ hnd->domain = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
+ if ( !hnd->domain )
+ return CAC_FAILURE;
- hnd->netbios_name[0] = '\0';
+ hnd->domain[0] = '\0';
- hnd->password = SMB_MALLOC_ARRAY(char, sizeof(fstring));
- if(!hnd->password)
- return CAC_FAILURE;
+ hnd->netbios_name = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
+ if ( !hnd->netbios_name )
+ return CAC_FAILURE;
- hnd->password[0] = '\0';
+ hnd->netbios_name[0] = '\0';
- hnd->server = SMB_MALLOC_ARRAY(char, sizeof(fstring));
- if(!hnd->server)
- return CAC_FAILURE;
+ hnd->password = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
+ if ( !hnd->password )
+ return CAC_FAILURE;
- hnd->server[0] = '\0';
+ hnd->password[0] = '\0';
- return CAC_SUCCESS;
+ hnd->server = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
+ if ( !hnd->server )
+ return CAC_FAILURE;
+
+ hnd->server[0] = '\0';
+
+ return CAC_SUCCESS;
}
-CacServerHandle *cac_NewServerHandle(BOOL allocate_fields) {
- CacServerHandle * hnd;
+CacServerHandle *cac_NewServerHandle( BOOL allocate_fields )
+{
+ CacServerHandle *hnd;
- hnd = SMB_MALLOC_P(CacServerHandle);
+ hnd = SMB_MALLOC_P( CacServerHandle );
- if(!hnd) {
- errno = ENOMEM;
- return NULL;
- }
-
- ZERO_STRUCTP(hnd);
+ if ( !hnd ) {
+ errno = ENOMEM;
+ return NULL;
+ }
- if(allocate_fields == True) {
- if(!cac_InitHandleMem(hnd)) {
- SAFE_FREE(hnd);
- return NULL;
- }
- }
+ ZERO_STRUCTP( hnd );
- hnd->_internal.ctx = smbc_new_context();
- if(!hnd->_internal.ctx) {
- cac_FreeHandle(hnd);
- return NULL;
- }
+ if ( allocate_fields == True ) {
+ if ( !cac_InitHandleMem( hnd ) ) {
+ SAFE_FREE( hnd );
+ return NULL;
+ }
+ }
- hnd->_internal.ctx->callbacks.auth_fn = cac_GetAuthDataFn;
-
- /*add defaults*/
- hnd->debug = 0;
+ hnd->_internal.ctx = smbc_new_context( );
+ if ( !hnd->_internal.ctx ) {
+ cac_FreeHandle( hnd );
+ return NULL;
+ }
- /*start at the highest and it will fall down after trying the functions*/
- hnd->_internal.srv_level = SRV_WIN_2K3;
+ hnd->_internal.ctx->callbacks.auth_fn = cac_GetAuthDataFn;
- hnd->_internal.user_supplied_ctx = False;
+ /*add defaults */
+ hnd->debug = 0;
- return hnd;
+ /*start at the highest and it will fall down after trying the functions */
+ hnd->_internal.srv_level = SRV_WIN_2K3;
+
+ hnd->_internal.user_supplied_ctx = False;
+
+ return hnd;
}
-int cac_InitHandleData(CacServerHandle *hnd) {
- /*store any automatically initialized values*/
- if(!hnd->netbios_name) {
- hnd->netbios_name = SMB_STRDUP(hnd->_internal.ctx->netbios_name);
- }
- else if(hnd->netbios_name[0] == '\0') {
- strncpy(hnd->netbios_name, hnd->_internal.ctx->netbios_name, sizeof(fstring));
- }
-
- if(!hnd->username) {
- hnd->username = SMB_STRDUP(hnd->_internal.ctx->user);
- }
- else if(hnd->username[0] == '\0') {
- strncpy(hnd->username, hnd->_internal.ctx->user, sizeof(fstring));
- }
-
- if(!hnd->domain) {
- hnd->domain = SMB_STRDUP(hnd->_internal.ctx->workgroup);
- }
- else if(hnd->domain[0] == '\0') {
- strncpy(hnd->domain, hnd->_internal.ctx->workgroup, sizeof(fstring));
- }
-
- return CAC_SUCCESS;
+int cac_InitHandleData( CacServerHandle * hnd )
+{
+ /*store any automatically initialized values */
+ if ( !hnd->netbios_name ) {
+ hnd->netbios_name =
+ SMB_STRDUP( hnd->_internal.ctx->netbios_name );
+ } else if ( hnd->netbios_name[0] == '\0' ) {
+ strncpy( hnd->netbios_name, hnd->_internal.ctx->netbios_name,
+ sizeof( fstring ) );
+ }
+
+ if ( !hnd->username ) {
+ hnd->username = SMB_STRDUP( hnd->_internal.ctx->user );
+ } else if ( hnd->username[0] == '\0' ) {
+ strncpy( hnd->username, hnd->_internal.ctx->user,
+ sizeof( fstring ) );
+ }
+
+ if ( !hnd->domain ) {
+ hnd->domain = SMB_STRDUP( hnd->_internal.ctx->workgroup );
+ } else if ( hnd->domain[0] == '\0' ) {
+ strncpy( hnd->domain, hnd->_internal.ctx->workgroup,
+ sizeof( fstring ) );
+ }
+
+ return CAC_SUCCESS;
}
-void cac_SetAuthDataFn(CacServerHandle *hnd, smbc_get_auth_data_fn auth_fn) {
- hnd->_internal.ctx->callbacks.auth_fn = auth_fn;
+void cac_SetAuthDataFn( CacServerHandle * hnd, smbc_get_auth_data_fn auth_fn )
+{
+ hnd->_internal.ctx->callbacks.auth_fn = auth_fn;
}
-void cac_SetSmbcContext(CacServerHandle *hnd, SMBCCTX *ctx) {
+void cac_SetSmbcContext( CacServerHandle * hnd, SMBCCTX * ctx )
+{
- SAFE_FREE(hnd->_internal.ctx);
+ SAFE_FREE( hnd->_internal.ctx );
- hnd->_internal.user_supplied_ctx = True;
+ hnd->_internal.user_supplied_ctx = True;
- hnd->_internal.ctx = ctx;
+ hnd->_internal.ctx = ctx;
/*_try_ to avoid any problems that might occur if cac_Connect() isn't called*/
- /*cac_InitHandleData(hnd);*/
+ /*cac_InitHandleData(hnd); */
}
/*used internally*/
-SMBCSRV *cac_GetServer(CacServerHandle *hnd) {
- SMBCSRV *srv;
-
- if(!hnd || !hnd->_internal.ctx) {
- return NULL;
- }
+SMBCSRV *cac_GetServer( CacServerHandle * hnd )
+{
+ SMBCSRV *srv;
+
+ if ( !hnd || !hnd->_internal.ctx ) {
+ return NULL;
+ }
+
+ srv = smbc_attr_server( hnd->_internal.ctx, hnd->server, "IPC$",
+ hnd->domain, hnd->username, hnd->password,
+ NULL );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_UNSUCCESSFUL;
+ DEBUG( 1,
+ ( "cac_GetServer: Could not find server connection.\n" ) );
+ }
+
+ return srv;
+}
- srv = smbc_attr_server(hnd->_internal.ctx, hnd->server, "IPC$", hnd->domain, hnd->username, hnd->password, NULL);
- if(!srv) {
- hnd->status=NT_STATUS_UNSUCCESSFUL;
- DEBUG(1, ("cac_GetServer: Could not find server connection.\n"));
- }
- return srv;
-}
+int cac_Connect( CacServerHandle * hnd, const char *srv )
+{
+ if ( !hnd ) {
+ return CAC_FAILURE;
+ }
+ /*these values should be initialized by the user */
+ if ( !hnd->server && !srv ) {
+ return CAC_FAILURE;
+ }
-int cac_Connect(CacServerHandle *hnd, const char *srv) {
- if(!hnd) {
- return CAC_FAILURE;
- }
- /*these values should be initialized by the user*/
- if(!hnd->server && !srv) {
- return CAC_FAILURE;
- }
+ /*change the server name in the server handle if necessary */
+ if ( srv && hnd->server && strcmp( hnd->server, srv ) == 0 ) {
+ SAFE_FREE( hnd->server );
+ hnd->server = SMB_STRDUP( srv );
+ }
- /*change the server name in the server handle if necessary*/
- if(srv && hnd->server && strcmp(hnd->server, srv) == 0) {
- SAFE_FREE(hnd->server);
- hnd->server = SMB_STRDUP(srv);
- }
+ /*first see if the context has already been setup */
+ if ( !( hnd->_internal.ctx->internal->_initialized ) ) {
+ hnd->_internal.ctx->debug = hnd->debug;
+ /*initialize the context */
+ if ( !smbc_init_context( hnd->_internal.ctx ) ) {
+ return CAC_FAILURE;
+ }
+ }
- /*first see if the context has already been setup*/
- if( !(hnd->_internal.ctx->internal->_initialized) ) {
- hnd->_internal.ctx->debug = hnd->debug;
+ /*copy any uninitialized values out of the smbc context into the handle */
+ if ( !cac_InitHandleData( hnd ) ) {
+ return CAC_FAILURE;
+ }
- /*initialize the context*/
- if(!smbc_init_context(hnd->_internal.ctx)) {
- return CAC_FAILURE;
- }
- }
+ DEBUG( 3, ( "cac_Connect: Username: %s\n", hnd->username ) );
+ DEBUG( 3, ( "cac_Connect: Domain: %s\n", hnd->domain ) );
+ DEBUG( 3, ( "cac_Connect: Netbios Name: %s\n", hnd->netbios_name ) );
- /*copy any uninitialized values out of the smbc context into the handle*/
- if(!cac_InitHandleData(hnd)) {
- return CAC_FAILURE;
- }
+ if ( !cac_GetServer( hnd ) ) {
+ return CAC_FAILURE;
+ }
- DEBUG(3, ("cac_Connect: Username: %s\n", hnd->username));
- DEBUG(3, ("cac_Connect: Domain: %s\n", hnd->domain));
- DEBUG(3, ("cac_Connect: Netbios Name: %s\n", hnd->netbios_name));
+ return CAC_SUCCESS;
- if(!cac_GetServer(hnd)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
-
}
-void cac_FreeHandle(CacServerHandle * hnd) {
- if(!hnd)
- return;
+void cac_FreeHandle( CacServerHandle * hnd )
+{
+ if ( !hnd )
+ return;
- /*only free the context if we created it*/
- if(!hnd->_internal.user_supplied_ctx) {
- smbc_free_context(hnd->_internal.ctx, True);
- }
+ /*only free the context if we created it */
+ if ( !hnd->_internal.user_supplied_ctx ) {
+ smbc_free_context( hnd->_internal.ctx, True );
+ }
- SAFE_FREE(hnd->netbios_name);
- SAFE_FREE(hnd->domain);
- SAFE_FREE(hnd->username);
- SAFE_FREE(hnd->password);
- SAFE_FREE(hnd->server);
- SAFE_FREE(hnd);
+ SAFE_FREE( hnd->netbios_name );
+ SAFE_FREE( hnd->domain );
+ SAFE_FREE( hnd->username );
+ SAFE_FREE( hnd->password );
+ SAFE_FREE( hnd->server );
+ SAFE_FREE( hnd );
}
-void cac_InitCacTime(CacTime *cactime, NTTIME nttime) {
- float high, low;
- uint32 sec;
+void cac_InitCacTime( CacTime * cactime, NTTIME nttime )
+{
+ float high, low;
+ uint32 sec;
- if(!cactime)
- return;
+ if ( !cactime )
+ return;
- ZERO_STRUCTP(cactime);
+ ZERO_STRUCTP( cactime );
- /*this code is taken from display_time() found in rpcclient/cmd_samr.c*/
- if (nttime.high==0 && nttime.low==0)
+ /*this code is taken from display_time() found in rpcclient/cmd_samr.c */
+ if ( nttime == 0 )
return;
- if (nttime.high==0x80000000 && nttime.low==0)
+ if ( nttime == 0x80000000000000LL )
return;
- high = 65536;
- high = high/10000;
- high = high*65536;
- high = high/1000;
- high = high * (~nttime.high);
-
- low = ~nttime.low;
- low = low/(1000*1000*10);
-
- sec=high+low;
-
- cactime->days=sec/(60*60*24);
- cactime->hours=(sec - (cactime->days*60*60*24)) / (60*60);
- cactime->minutes=(sec - (cactime->days*60*60*24) - (cactime->hours*60*60) ) / 60;
- cactime->seconds=sec - (cactime->days*60*60*24) - (cactime->hours*60*60) - (cactime->minutes*60);
+ high = 65536;
+ high = high / 10000;
+ high = high * 65536;
+ high = high / 1000;
+ high = high * ( ~( nttime >> 32 ) );
+
+ low = ~( nttime & 0xFFFFFFFF );
+ low = low / ( 1000 * 1000 * 10 );
+
+ sec = high + low;
+
+ cactime->days = sec / ( 60 * 60 * 24 );
+ cactime->hours =
+ ( sec - ( cactime->days * 60 * 60 * 24 ) ) / ( 60 * 60 );
+ cactime->minutes =
+ ( sec - ( cactime->days * 60 * 60 * 24 ) -
+ ( cactime->hours * 60 * 60 ) ) / 60;
+ cactime->seconds =
+ sec - ( cactime->days * 60 * 60 * 24 ) -
+ ( cactime->hours * 60 * 60 ) - ( cactime->minutes * 60 );
}
-void cac_GetAuthDataFn(const char * pServer,
- const char * pShare,
- char * pWorkgroup,
- int maxLenWorkgroup,
- char * pUsername,
- int maxLenUsername,
- char * pPassword,
- int maxLenPassword)
-
+void cac_GetAuthDataFn( const char *pServer,
+ const char *pShare,
+ char *pWorkgroup,
+ int maxLenWorkgroup,
+ char *pUsername,
+ int maxLenUsername,
+ char *pPassword, int maxLenPassword )
{
- char temp[sizeof(fstring)];
-
- static char authUsername[sizeof(fstring)];
- static char authWorkgroup[sizeof(fstring)];
- static char authPassword[sizeof(fstring)];
- static char authSet = 0;
-
- char *pass = NULL;
-
-
- if (authSet)
- {
- strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1);
- strncpy(pUsername, authUsername, maxLenUsername - 1);
- strncpy(pPassword, authPassword, maxLenPassword - 1);
- }
- else
- {
- d_printf("Domain: [%s] ", pWorkgroup);
- fgets(temp, sizeof(fstring), stdin);
-
- if (temp[strlen(temp) - 1] == '\n') /* A new line? */
- {
- temp[strlen(temp) - 1] = '\0';
- }
-
-
- if (temp[0] != '\0')
- {
- strncpy(pWorkgroup, temp, maxLenWorkgroup - 1);
- strncpy(authWorkgroup, temp, maxLenWorkgroup - 1);
- }
-
- d_printf("Username: [%s] ", pUsername);
- fgets(temp, sizeof(fstring), stdin);
-
- if (temp[strlen(temp) - 1] == '\n') /* A new line? */
- {
- temp[strlen(temp) - 1] = '\0';
- }
-
- if (temp[0] != '\0')
- {
- strncpy(pUsername, temp, maxLenUsername - 1);
- strncpy(authUsername, pUsername, maxLenUsername - 1);
- }
-
- pass = getpass("Password: ");
- if (pass)
- fstrcpy(temp, pass);
- if (temp[strlen(temp) - 1] == '\n') /* A new line? */
- {
- temp[strlen(temp) - 1] = '\0';
- }
- if (temp[0] != '\0')
- {
- strncpy(pPassword, temp, maxLenPassword - 1);
- strncpy(authPassword, pPassword, maxLenPassword - 1);
- }
- authSet = 1;
- }
+ char temp[sizeof( fstring )];
+
+ static char authUsername[sizeof( fstring )];
+ static char authWorkgroup[sizeof( fstring )];
+ static char authPassword[sizeof( fstring )];
+ static char authSet = 0;
+
+ char *pass = NULL;
+
+
+ if ( authSet ) {
+ strncpy( pWorkgroup, authWorkgroup, maxLenWorkgroup - 1 );
+ strncpy( pUsername, authUsername, maxLenUsername - 1 );
+ strncpy( pPassword, authPassword, maxLenPassword - 1 );
+ } else {
+ d_printf( "Domain: [%s] ", pWorkgroup );
+ fgets( temp, sizeof( fstring ), stdin );
+
+ if ( temp[strlen( temp ) - 1] == '\n' ) { /* A new line? */
+ temp[strlen( temp ) - 1] = '\0';
+ }
+
+
+ if ( temp[0] != '\0' ) {
+ strncpy( pWorkgroup, temp, maxLenWorkgroup - 1 );
+ strncpy( authWorkgroup, temp, maxLenWorkgroup - 1 );
+ }
+
+ d_printf( "Username: [%s] ", pUsername );
+ fgets( temp, sizeof( fstring ), stdin );
+
+ if ( temp[strlen( temp ) - 1] == '\n' ) { /* A new line? */
+ temp[strlen( temp ) - 1] = '\0';
+ }
+
+ if ( temp[0] != '\0' ) {
+ strncpy( pUsername, temp, maxLenUsername - 1 );
+ strncpy( authUsername, pUsername,
+ maxLenUsername - 1 );
+ }
+
+ pass = getpass( "Password: " );
+ if ( pass )
+ fstrcpy( temp, pass );
+ if ( temp[strlen( temp ) - 1] == '\n' ) { /* A new line? */
+ temp[strlen( temp ) - 1] = '\0';
+ }
+ if ( temp[0] != '\0' ) {
+ strncpy( pPassword, temp, maxLenPassword - 1 );
+ strncpy( authPassword, pPassword,
+ maxLenPassword - 1 );
+ }
+ authSet = 1;
+ }
}
-
diff --git a/source/libmsrpc/libmsrpc_internal.c b/source/libmsrpc/libmsrpc_internal.c
index 3a47361db29..c062b47ede5 100644
--- a/source/libmsrpc/libmsrpc_internal.c
+++ b/source/libmsrpc/libmsrpc_internal.c
@@ -1,3 +1,4 @@
+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client internal functions
@@ -22,690 +23,743 @@
#include "libmsrpc.h"
#include "libmsrpc_internal.h"
+char *cac_unistr_to_str( TALLOC_CTX * mem_ctx, uint16 * src, int num_bytes );
+char *talloc_unistr2_to_ascii( TALLOC_CTX * mem_ctx, UNISTR2 str );
+char *cac_unistr_ascii( TALLOC_CTX * mem_ctx, UNISTR src );
+
/*used to get a struct rpc_pipe_client* to be passed into rpccli* calls*/
-struct rpc_pipe_client *cac_GetPipe(CacServerHandle *hnd, int pi_idx) {
- SMBCSRV *srv = NULL;
- struct rpc_pipe_client *pipe_hnd = NULL;
+struct rpc_pipe_client *cac_GetPipe( CacServerHandle * hnd, int pi_idx )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return NULL;
+ if ( !hnd ) {
+ return NULL;
+ }
- if(hnd->_internal.pipes[pi_idx] == False) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return NULL;
- }
+ if ( hnd->_internal.pipes[pi_idx] == False ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return NULL;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return NULL;
- }
+ srv = cac_GetServer( hnd );
+ if ( !srv ) {
+ hnd->status = NT_STATUS_INVALID_CONNECTION;
+ return NULL;
+ }
- pipe_hnd = srv->cli.pipe_list;
+ pipe_hnd = srv->cli->pipe_list;
- while(pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx)
- pipe_hnd = pipe_hnd->next;
+ while ( pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx ) {
+ pipe_hnd = pipe_hnd->next;
+ }
- return pipe_hnd;
+ return pipe_hnd;
}
/*takes a string like HKEY_LOCAL_MACHINE\HARDWARE\ACPI and returns the reg_type code and then a pointer to the start of the path (HARDWARE)*/
-int cac_ParseRegPath(char *path, uint32 *reg_type, char **key_name) {
-
- if(!path)
- return CAC_FAILURE;
-
- if(strncmp(path, "HKLM", 4) == 0) {
- *reg_type = HKEY_LOCAL_MACHINE;
- *key_name = (path[4] == '\\') ? path + 5 : NULL;
- }
- else if(strncmp(path, "HKEY_LOCAL_MACHINE", 18) == 0) {
- *reg_type = HKEY_LOCAL_MACHINE;
- *key_name = (path[18] == '\\') ? path + 19 : NULL;
- }
- else if(strncmp(path, "HKCR", 4) == 0) {
- *reg_type = HKEY_CLASSES_ROOT;
- *key_name = (path[4] == '\\') ? path + 5 : NULL;
- }
- else if(strncmp(path, "HKEY_CLASSES_ROOT", 17) == 0) {
- *reg_type = HKEY_CLASSES_ROOT;
- *key_name = (path[17] == '\\') ? path + 18 : NULL;
- }
- else if(strncmp(path, "HKU", 3) == 0) {
- *reg_type = HKEY_USERS;
- *key_name = (path[3] == '\\') ? path + 4 : NULL;
- }
- else if(strncmp(path, "HKEY_USERS", 10) == 0) {
- *reg_type = HKEY_USERS;
- *key_name = (path[10] == '\\') ? path + 11 : NULL;
- }
- else if(strncmp(path, "HKPD", 4) == 0) {
- *reg_type = HKEY_PERFORMANCE_DATA;
- *key_name = (path[4] == '\\') ? path + 5 : NULL;
- }
- else if(strncmp(path, "HKEY_PERFORMANCE_DATA", 21) == 0) {
- *reg_type = HKEY_PERFORMANCE_DATA;
- *key_name = (path[21] == '\\') ? path + 22 : NULL;
- }
- else {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
+int cac_ParseRegPath( char *path, uint32 * reg_type, char **key_name )
+{
+
+ if ( !path )
+ return CAC_FAILURE;
+
+ if ( strncmp( path, "HKLM", 4 ) == 0 ) {
+ *reg_type = HKEY_LOCAL_MACHINE;
+ *key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
+ } else if ( strncmp( path, "HKEY_LOCAL_MACHINE", 18 ) == 0 ) {
+ *reg_type = HKEY_LOCAL_MACHINE;
+ *key_name = ( path[18] == '\\' ) ? path + 19 : NULL;
+ } else if ( strncmp( path, "HKCR", 4 ) == 0 ) {
+ *reg_type = HKEY_CLASSES_ROOT;
+ *key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
+ } else if ( strncmp( path, "HKEY_CLASSES_ROOT", 17 ) == 0 ) {
+ *reg_type = HKEY_CLASSES_ROOT;
+ *key_name = ( path[17] == '\\' ) ? path + 18 : NULL;
+ } else if ( strncmp( path, "HKU", 3 ) == 0 ) {
+ *reg_type = HKEY_USERS;
+ *key_name = ( path[3] == '\\' ) ? path + 4 : NULL;
+ } else if ( strncmp( path, "HKEY_USERS", 10 ) == 0 ) {
+ *reg_type = HKEY_USERS;
+ *key_name = ( path[10] == '\\' ) ? path + 11 : NULL;
+ } else if ( strncmp( path, "HKPD", 4 ) == 0 ) {
+ *reg_type = HKEY_PERFORMANCE_DATA;
+ *key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
+ } else if ( strncmp( path, "HKEY_PERFORMANCE_DATA", 21 ) == 0 ) {
+ *reg_type = HKEY_PERFORMANCE_DATA;
+ *key_name = ( path[21] == '\\' ) ? path + 22 : NULL;
+ } else {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VALUE_DATA data) {
- RPC_DATA_BLOB *blob = NULL;
- int i;
- uint32 size = 0;
- uint8 *multi = NULL;
- uint32 multi_idx = 0;
-
- blob = talloc(mem_ctx, RPC_DATA_BLOB);
-
- if(!blob) {
- errno = ENOMEM;
- return NULL;
- }
-
- switch(data_type) {
- case REG_SZ:
- init_rpc_blob_str(blob, data.reg_sz, strlen(data.reg_sz ) + 1);
- break;
-
- case REG_EXPAND_SZ:
- init_rpc_blob_str(blob, data.reg_expand_sz, strlen(data.reg_sz) + 1);
- break;
-
- case REG_BINARY:
- init_rpc_blob_bytes(blob, data.reg_binary.data, data.reg_binary.data_length);
- break;
-
- case REG_DWORD:
- init_rpc_blob_uint32(blob, data.reg_dword);
- break;
-
- case REG_DWORD_BE:
- init_rpc_blob_uint32(blob, data.reg_dword_be);
- break;
-
- case REG_MULTI_SZ:
- /*need to find the size*/
- for(i = 0; i < data.reg_multi_sz.num_strings; i++) {
- size += strlen(data.reg_multi_sz.strings[i]) + 1;
- }
-
- /**need a whole bunch of unicode strings in a row (seperated by null characters), with an extra null-character on the end*/
-
- multi = TALLOC_ZERO_ARRAY(mem_ctx, uint8, (size + 1)*2); /*size +1 for the extra null character*/
- if(!multi) {
- errno = ENOMEM;
- break;
- }
-
- /*do it using rpcstr_push()*/
- multi_idx = 0;
- for(i = 0; i < data.reg_multi_sz.num_strings; i++) {
- size_t len = strlen(data.reg_multi_sz.strings[i]) + 1;
-
- rpcstr_push((multi + multi_idx), data.reg_multi_sz.strings[i], len * 2, STR_TERMINATE);
-
- /* x2 becuase it is a uint8 buffer*/
- multi_idx += len * 2;
- }
-
- /*now initialize the buffer as binary data*/
- init_rpc_blob_bytes(blob, multi, (size + 1)*2);
-
- break;
-
- default:
- TALLOC_FREE(blob);
- blob = NULL;
- return NULL;
- }
-
- if(!(blob->buffer)) {
- TALLOC_FREE(blob);
- return NULL;
- }
-
- return blob;
+RPC_DATA_BLOB *cac_MakeRpcDataBlob( TALLOC_CTX * mem_ctx, uint32 data_type,
+ REG_VALUE_DATA data )
+{
+ RPC_DATA_BLOB *blob = NULL;
+ int i;
+ uint32 size = 0;
+ uint8 *multi = NULL;
+ uint32 multi_idx = 0;
+
+ blob = talloc( mem_ctx, RPC_DATA_BLOB );
+
+ if ( !blob ) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ switch ( data_type ) {
+ case REG_SZ:
+ init_rpc_blob_str( blob, data.reg_sz,
+ strlen( data.reg_sz ) + 1 );
+ break;
+
+ case REG_EXPAND_SZ:
+ init_rpc_blob_str( blob, data.reg_expand_sz,
+ strlen( data.reg_sz ) + 1 );
+ break;
+
+ case REG_BINARY:
+ init_rpc_blob_bytes( blob, data.reg_binary.data,
+ data.reg_binary.data_length );
+ break;
+
+ case REG_DWORD:
+ init_rpc_blob_uint32( blob, data.reg_dword );
+ break;
+
+ case REG_DWORD_BE:
+ init_rpc_blob_uint32( blob, data.reg_dword_be );
+ break;
+
+ case REG_MULTI_SZ:
+ /*need to find the size */
+ for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) {
+ size += strlen( data.reg_multi_sz.strings[i] ) + 1;
+ }
+
+ /**need a whole bunch of unicode strings in a row (seperated by null characters), with an extra null-character on the end*/
+
+ multi = TALLOC_ZERO_ARRAY( mem_ctx, uint8, ( size + 1 ) * 2 ); /*size +1 for the extra null character */
+ if ( !multi ) {
+ errno = ENOMEM;
+ break;
+ }
+
+ /*do it using rpcstr_push() */
+ multi_idx = 0;
+ for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) {
+ size_t len =
+ strlen( data.reg_multi_sz.strings[i] ) + 1;
+
+ rpcstr_push( ( multi + multi_idx ),
+ data.reg_multi_sz.strings[i], len * 2,
+ STR_TERMINATE );
+
+ /* x2 becuase it is a uint8 buffer */
+ multi_idx += len * 2;
+ }
+
+ /*now initialize the buffer as binary data */
+ init_rpc_blob_bytes( blob, multi, ( size + 1 ) * 2 );
+
+ break;
+
+ default:
+ TALLOC_FREE( blob );
+ blob = NULL;
+ return NULL;
+ }
+
+ if ( !( blob->buffer ) ) {
+ TALLOC_FREE( blob );
+ return NULL;
+ }
+
+ return blob;
}
/*turns a string in a uint16 array to a char array*/
-char *cac_unistr_to_str(TALLOC_CTX *mem_ctx, uint16 *src, int num_bytes) {
- char *buf;
-
- int i = 0;
-
- uint32 str_len = 0;
-
- /*don't allocate more space than we need*/
- while( (str_len) < num_bytes/2 && src[str_len] != 0x0000)
- str_len++;
+char *cac_unistr_to_str( TALLOC_CTX * mem_ctx, uint16 * src, int num_bytes )
+{
+ char *buf;
- /*need room for a '\0'*/
- str_len++;
+ int i = 0;
- buf = talloc_array(mem_ctx, char, str_len);
- if(!buf) {
- return NULL;
- }
+ uint32 str_len = 0;
- for(i = 0; i < num_bytes/2; i++) {
- buf[i] = ((char *)src)[2*i];
- }
+ /*don't allocate more space than we need */
+ while ( ( str_len ) < num_bytes / 2 && src[str_len] != 0x0000 )
+ str_len++;
- buf[str_len - 1] = '\0';
+ /*need room for a '\0' */
+ str_len++;
- return buf;
-}
+ buf = talloc_array( mem_ctx, char, str_len );
-REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGVAL_BUFFER buf) {
- REG_VALUE_DATA *data;
-
- uint32 i;
-
- /*all of the following used for MULTI_SZ data*/
- uint32 size = 0;
- uint32 len = 0;
- uint32 multi_idx = 0;
- uint32 num_strings= 0;
- char **strings = NULL;
-
- data = talloc(mem_ctx, REG_VALUE_DATA);
- if(!data) {
- errno = ENOMEM;
- return NULL;
- }
-
- switch (data_type) {
- case REG_SZ:
- data->reg_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len);
- if(!data->reg_sz) {
- TALLOC_FREE(data);
- errno = ENOMEM;
- data = NULL;
- }
-
- break;
-
- case REG_EXPAND_SZ:
- data->reg_expand_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len);
-
- if(!data->reg_expand_sz) {
- TALLOC_FREE(data);
- errno = ENOMEM;
- data = NULL;
- }
-
- break;
-
- case REG_BINARY:
- size = buf.buf_len;
-
- data->reg_binary.data_length = size;
-
- data->reg_binary.data = talloc_memdup(mem_ctx, buf.buffer, size);
- if(!data->reg_binary.data) {
- TALLOC_FREE(data);
- errno = ENOMEM;
- data = NULL;
- }
- break;
-
- case REG_DWORD:
- data->reg_dword = *((uint32 *)buf.buffer);
- break;
-
- case REG_DWORD_BE:
- data->reg_dword_be = *((uint32 *)buf.buffer);
- break;
-
- case REG_MULTI_SZ:
- size = buf.buf_len;
-
- /*find out how many strings there are. size is # of bytes and we want to work uint16*/
- for(i = 0; i < (size/2 - 1); i++) {
- if(buf.buffer[i] == 0x0000)
- num_strings++;
-
- /*buffer is suppsed to be terminated with \0\0, but it might not be*/
- if(buf.buffer[i] == 0x0000 && buf.buffer[i + 1] == 0x0000)
- break;
- }
-
- strings = talloc_array(mem_ctx, char *, num_strings);
- if(!strings) {
- errno = ENOMEM;
- TALLOC_FREE(data);
- break;
- }
-
- if(num_strings == 0) /*then our work here is done*/
- break;
-
- for(i = 0; i < num_strings; i++) {
- /*find out how many characters are in this string*/
- len = 0;
- /*make sure we don't go past the end of the buffer and keep looping until we have a uni \0*/
- while( multi_idx + len < size/2 && buf.buffer[multi_idx + len] != 0x0000)
- len++;
-
- /*stay aware of the \0\0*/
- len++;
-
- strings[i] = TALLOC_ZERO_ARRAY(mem_ctx, char, len);
-
- /*pull out the unicode string*/
- rpcstr_pull(strings[i], (buf.buffer + multi_idx) , len, -1, STR_TERMINATE);
-
- /*keep track of where we are in the bigger array*/
- multi_idx += len;
- }
-
- data->reg_multi_sz.num_strings = num_strings;
- data->reg_multi_sz.strings = strings;
-
- break;
-
- default:
- TALLOC_FREE(data);
- data = NULL;
- }
-
- return data;
-}
+ if ( !buf ) {
+ return NULL;
+ }
-SAM_USERINFO_CTR *cac_MakeUserInfoCtr(TALLOC_CTX *mem_ctx, CacUserInfo *info) {
- SAM_USERINFO_CTR *ctr = NULL;
-
- /*the flags we are 'setting'- include/passdb.h*/
- uint32 flags = ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID | ACCT_ADMIN_DESC | ACCT_DESCRIPTION |
- ACCT_HOME_DIR | ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE | ACCT_WORKSTATIONS |
- ACCT_FLAGS;
-
- NTTIME logon_time;
- NTTIME logoff_time;
- NTTIME kickoff_time;
- NTTIME pass_last_set_time;
- NTTIME pass_can_change_time;
- NTTIME pass_must_change_time;
-
- UNISTR2 user_name;
- UNISTR2 full_name;
- UNISTR2 home_dir;
- UNISTR2 dir_drive;
- UNISTR2 log_scr;
- UNISTR2 prof_path;
- UNISTR2 desc;
- UNISTR2 wkstas;
- UNISTR2 mung_dial;
- UNISTR2 unk;
-
- ctr = talloc(mem_ctx, SAM_USERINFO_CTR);
- if(!ctr)
- return NULL;
-
- ZERO_STRUCTP(ctr->info.id23);
-
- ctr->info.id21 = talloc(mem_ctx, SAM_USER_INFO_21);
- if(!ctr->info.id21)
- return NULL;
-
- ctr->switch_value = 21;
-
- ZERO_STRUCTP(ctr->info.id21);
-
- unix_to_nt_time(&logon_time, info->logon_time);
- unix_to_nt_time(&logoff_time, info->logoff_time);
- unix_to_nt_time(&kickoff_time, info->kickoff_time);
- unix_to_nt_time(&pass_last_set_time, info->pass_last_set_time);
- unix_to_nt_time(&pass_can_change_time, info->pass_can_change_time);
- unix_to_nt_time(&pass_must_change_time, info->pass_must_change_time);
-
- /*initialize the strings*/
- init_unistr2(&user_name, info->username, UNI_STR_TERMINATE);
- init_unistr2(&full_name, info->full_name, UNI_STR_TERMINATE);
- init_unistr2(&home_dir, info->home_dir, UNI_STR_TERMINATE);
- init_unistr2(&dir_drive, info->home_drive, UNI_STR_TERMINATE);
- init_unistr2(&log_scr, info->logon_script, UNI_STR_TERMINATE);
- init_unistr2(&prof_path, info->profile_path, UNI_STR_TERMINATE);
- init_unistr2(&desc, info->description, UNI_STR_TERMINATE);
- init_unistr2(&wkstas, info->workstations, UNI_STR_TERMINATE);
- init_unistr2(&unk, "\0", UNI_STR_TERMINATE);
- init_unistr2(&mung_dial, info->dial, UNI_STR_TERMINATE);
-
- /*manually set passmustchange*/
- ctr->info.id21->passmustchange = (info->pass_must_change) ? 0x01 : 0x00;
-
- init_sam_user_info21W(ctr->info.id21,
- &logon_time,
- &logoff_time,
- &kickoff_time,
- &pass_last_set_time,
- &pass_can_change_time,
- &pass_must_change_time,
- &user_name,
- &full_name,
- &home_dir,
- &dir_drive,
- &log_scr,
- &prof_path,
- &desc,
- &wkstas,
- &unk,
- &mung_dial,
- info->lm_password,
- info->nt_password,
- info->rid,
- info->group_rid,
- info->acb_mask,
- flags,
- 168, /*logon divs*/
- info->logon_hours,
- info->bad_passwd_count,
- info->logon_count);
-
- return ctr;
-
-}
+ for ( i = 0; i < num_bytes / 2; i++ ) {
+ buf[i] = ( ( char * ) src )[2 * i];
+ }
-char *talloc_unistr2_to_ascii(TALLOC_CTX *mem_ctx, UNISTR2 str) {
- char *buf = NULL;
+ buf[str_len - 1] = '\0';
- if(!mem_ctx)
- return NULL;
-
- buf = talloc_array(mem_ctx, char, (str.uni_str_len + 1));
- if(!buf)
- return NULL;
-
- unistr2_to_ascii(buf, &str, str.uni_str_len + 1);
-
- return buf;
+ return buf;
}
-CacUserInfo *cac_MakeUserInfo(TALLOC_CTX *mem_ctx, SAM_USERINFO_CTR *ctr) {
- CacUserInfo *info = NULL;
- SAM_USER_INFO_21 *id21 = NULL;
-
- if(!ctr || ctr->switch_value != 21)
- return NULL;
-
- info = talloc(mem_ctx, CacUserInfo);
- if(!info)
- return NULL;
-
- id21 = ctr->info.id21;
-
- ZERO_STRUCTP(info);
-
- info->logon_time = nt_time_to_unix(&id21->logon_time);
- info->logoff_time = nt_time_to_unix(&id21->logoff_time);
- info->kickoff_time = nt_time_to_unix(&id21->kickoff_time);
- info->pass_last_set_time = nt_time_to_unix(&id21->pass_last_set_time);
- info->pass_can_change_time = nt_time_to_unix(&id21->pass_can_change_time);
- info->pass_must_change_time = nt_time_to_unix(&id21->pass_must_change_time);
-
- info->username = talloc_unistr2_to_ascii(mem_ctx, id21->uni_user_name);
- if(!info->username)
- return NULL;
-
- info->full_name = talloc_unistr2_to_ascii(mem_ctx, id21->uni_full_name);
- if(!info->full_name)
- return NULL;
-
- info->home_dir = talloc_unistr2_to_ascii(mem_ctx, id21->uni_home_dir);
- if(!info->home_dir)
- return NULL;
-
- info->home_drive = talloc_unistr2_to_ascii(mem_ctx, id21->uni_dir_drive);
- if(!info->home_drive)
- return NULL;
-
- info->logon_script = talloc_unistr2_to_ascii(mem_ctx, id21->uni_logon_script);
- if(!info->logon_script)
- return NULL;
-
- info->profile_path = talloc_unistr2_to_ascii(mem_ctx, id21->uni_profile_path);
- if(!info->profile_path)
- return NULL;
-
- info->description = talloc_unistr2_to_ascii(mem_ctx, id21->uni_acct_desc);
- if(!info->description)
- return NULL;
-
- info->workstations = talloc_unistr2_to_ascii(mem_ctx, id21->uni_workstations);
- if(!info->workstations)
- return NULL;
-
- info->dial = talloc_unistr2_to_ascii(mem_ctx, id21->uni_munged_dial);
- if(!info->dial)
- return NULL;
-
- info->rid = id21->user_rid;
- info->group_rid = id21->group_rid;
- info->acb_mask = id21->acb_info;
- info->bad_passwd_count = id21->bad_password_count;
- info->logon_count = id21->logon_count;
-
- memcpy(info->nt_password, id21->nt_pwd, 8);
- memcpy(info->lm_password, id21->lm_pwd, 8);
-
- info->logon_hours = talloc_memdup(mem_ctx, &(id21->logon_hrs), sizeof(LOGON_HRS));
- if(!info->logon_hours)
- return NULL;
-
- info->pass_must_change = (id21->passmustchange) ? True : False;
-
- return info;
+REG_VALUE_DATA *cac_MakeRegValueData( TALLOC_CTX * mem_ctx, uint32 data_type,
+ REGVAL_BUFFER buf )
+{
+ REG_VALUE_DATA *data;
+
+ uint32 i;
+
+ /*all of the following used for MULTI_SZ data */
+ uint32 size = 0;
+ uint32 len = 0;
+ uint32 multi_idx = 0;
+ uint32 num_strings = 0;
+ char **strings = NULL;
+
+ data = talloc( mem_ctx, REG_VALUE_DATA );
+ if ( !data ) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ switch ( data_type ) {
+ case REG_SZ:
+ data->reg_sz =
+ cac_unistr_to_str( mem_ctx, buf.buffer, buf.buf_len );
+ if ( !data->reg_sz ) {
+ TALLOC_FREE( data );
+ errno = ENOMEM;
+ data = NULL;
+ }
+
+ break;
+
+ case REG_EXPAND_SZ:
+ data->reg_expand_sz =
+ cac_unistr_to_str( mem_ctx, buf.buffer, buf.buf_len );
+
+ if ( !data->reg_expand_sz ) {
+ TALLOC_FREE( data );
+ errno = ENOMEM;
+ data = NULL;
+ }
+
+ break;
+
+ case REG_BINARY:
+ size = buf.buf_len;
+
+ data->reg_binary.data_length = size;
+
+ data->reg_binary.data =
+ ( uint8 * ) talloc_memdup( mem_ctx, buf.buffer,
+ size );
+ if ( !data->reg_binary.data ) {
+ TALLOC_FREE( data );
+ errno = ENOMEM;
+ data = NULL;
+ }
+ break;
+
+ case REG_DWORD:
+ data->reg_dword = *( ( uint32 * ) buf.buffer );
+ break;
+
+ case REG_DWORD_BE:
+ data->reg_dword_be = *( ( uint32 * ) buf.buffer );
+ break;
+
+ case REG_MULTI_SZ:
+ size = buf.buf_len;
+
+ /*find out how many strings there are. size is # of bytes and we want to work uint16 */
+ for ( i = 0; i < ( size / 2 - 1 ); i++ ) {
+ if ( buf.buffer[i] == 0x0000 )
+ num_strings++;
+
+ /*buffer is suppsed to be terminated with \0\0, but it might not be */
+ if ( buf.buffer[i] == 0x0000
+ && buf.buffer[i + 1] == 0x0000 )
+ break;
+ }
+
+ strings = talloc_array( mem_ctx, char *, num_strings );
+
+ if ( !strings ) {
+ errno = ENOMEM;
+ TALLOC_FREE( data );
+ break;
+ }
+
+ if ( num_strings == 0 ) /*then our work here is done */
+ break;
+
+ for ( i = 0; i < num_strings; i++ ) {
+ /*find out how many characters are in this string */
+ len = 0;
+ /*make sure we don't go past the end of the buffer and keep looping until we have a uni \0 */
+ while ( multi_idx + len < size / 2
+ && buf.buffer[multi_idx + len] != 0x0000 )
+ len++;
+
+ /*stay aware of the \0\0 */
+ len++;
+
+ strings[i] = TALLOC_ZERO_ARRAY( mem_ctx, char, len );
+
+ /*pull out the unicode string */
+ rpcstr_pull( strings[i], ( buf.buffer + multi_idx ),
+ len, -1, STR_TERMINATE );
+
+ /*keep track of where we are in the bigger array */
+ multi_idx += len;
+ }
+
+ data->reg_multi_sz.num_strings = num_strings;
+ data->reg_multi_sz.strings = strings;
+
+ break;
+
+ default:
+ TALLOC_FREE( data );
+ data = NULL;
+ }
+
+ return data;
}
-CacGroupInfo *cac_MakeGroupInfo(TALLOC_CTX *mem_ctx, GROUP_INFO_CTR *ctr) {
- CacGroupInfo *info = NULL;
-
- if(!mem_ctx || !ctr || ctr->switch_value1 != 1)
- return NULL;
-
- info = talloc(mem_ctx, CacGroupInfo);
- if(!info)
- return NULL;
+SAM_USERINFO_CTR *cac_MakeUserInfoCtr( TALLOC_CTX * mem_ctx,
+ CacUserInfo * info )
+{
+ SAM_USERINFO_CTR *ctr = NULL;
+
+ /*the flags we are 'setting'- include/passdb.h */
+ uint32 flags =
+ ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID |
+ ACCT_DESCRIPTION | ACCT_COMMENT | ACCT_HOME_DIR |
+ ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE |
+ ACCT_WORKSTATIONS | ACCT_FLAGS;
+
+ NTTIME logon_time;
+ NTTIME logoff_time;
+ NTTIME kickoff_time;
+ NTTIME pass_last_set_time;
+ NTTIME pass_can_change_time;
+ NTTIME pass_must_change_time;
+
+ UNISTR2 user_name;
+ UNISTR2 full_name;
+ UNISTR2 home_dir;
+ UNISTR2 dir_drive;
+ UNISTR2 log_scr;
+ UNISTR2 prof_path;
+ UNISTR2 desc;
+ UNISTR2 wkstas;
+ UNISTR2 mung_dial;
+ UNISTR2 unk;
+
+ ctr = talloc( mem_ctx, SAM_USERINFO_CTR );
+ if ( !ctr )
+ return NULL;
+
+ ZERO_STRUCTP( ctr->info.id23 );
+
+ ctr->info.id21 = talloc( mem_ctx, SAM_USER_INFO_21 );
+ if ( !ctr->info.id21 )
+ return NULL;
+
+ ctr->switch_value = 21;
+
+ ZERO_STRUCTP( ctr->info.id21 );
+
+ unix_to_nt_time( &logon_time, info->logon_time );
+ unix_to_nt_time( &logoff_time, info->logoff_time );
+ unix_to_nt_time( &kickoff_time, info->kickoff_time );
+ unix_to_nt_time( &pass_last_set_time, info->pass_last_set_time );
+ unix_to_nt_time( &pass_can_change_time, info->pass_can_change_time );
+ unix_to_nt_time( &pass_must_change_time,
+ info->pass_must_change_time );
+
+ /*initialize the strings */
+ init_unistr2( &user_name, info->username, UNI_STR_TERMINATE );
+ init_unistr2( &full_name, info->full_name, UNI_STR_TERMINATE );
+ init_unistr2( &home_dir, info->home_dir, UNI_STR_TERMINATE );
+ init_unistr2( &dir_drive, info->home_drive, UNI_STR_TERMINATE );
+ init_unistr2( &log_scr, info->logon_script, UNI_STR_TERMINATE );
+ init_unistr2( &prof_path, info->profile_path, UNI_STR_TERMINATE );
+ init_unistr2( &desc, info->description, UNI_STR_TERMINATE );
+ init_unistr2( &wkstas, info->workstations, UNI_STR_TERMINATE );
+ init_unistr2( &unk, "\0", UNI_STR_TERMINATE );
+ init_unistr2( &mung_dial, info->dial, UNI_STR_TERMINATE );
+
+ /*manually set passmustchange */
+ ctr->info.id21->passmustchange =
+ ( info->pass_must_change ) ? 0x01 : 0x00;
+
+ init_sam_user_info21W( ctr->info.id21, &logon_time, &logoff_time, &kickoff_time, &pass_last_set_time, &pass_can_change_time, &pass_must_change_time, &user_name, &full_name, &home_dir, &dir_drive, &log_scr, &prof_path, &desc, &wkstas, &unk, &mung_dial, info->lm_password, info->nt_password, info->rid, info->group_rid, info->acb_mask, flags, 168, /*logon divs */
+ info->logon_hours,
+ info->bad_passwd_count, info->logon_count );
+
+ return ctr;
- info->name = talloc_unistr2_to_ascii(mem_ctx, ctr->group.info1.uni_acct_name);
- if(!info->name)
- return NULL;
-
- info->description = talloc_unistr2_to_ascii(mem_ctx, ctr->group.info1.uni_acct_desc);
- if(!info->description)
- return NULL;
-
- info->num_members = ctr->group.info1.num_members;
-
- return info;
}
-GROUP_INFO_CTR *cac_MakeGroupInfoCtr(TALLOC_CTX *mem_ctx, CacGroupInfo *info) {
- GROUP_INFO_CTR *ctr = NULL;
+char *talloc_unistr2_to_ascii( TALLOC_CTX * mem_ctx, UNISTR2 str )
+{
+ char *buf = NULL;
- if(!mem_ctx || !info)
- return NULL;
+ if ( !mem_ctx )
+ return NULL;
- ctr = talloc(mem_ctx, GROUP_INFO_CTR);
- if(!ctr)
- return NULL;
+ buf = talloc_array( mem_ctx, char, ( str.uni_str_len + 1 ) );
+ if ( !buf )
+ return NULL;
- ctr->switch_value1 = 1;
+ unistr2_to_ascii( buf, &str, str.uni_str_len + 1 );
- init_samr_group_info1(&(ctr->group.info1), info->name, info->description, info->num_members);
+ return buf;
+}
- return ctr;
+CacUserInfo *cac_MakeUserInfo( TALLOC_CTX * mem_ctx, SAM_USERINFO_CTR * ctr )
+{
+ CacUserInfo *info = NULL;
+ SAM_USER_INFO_21 *id21 = NULL;
+
+ if ( !ctr || ctr->switch_value != 21 )
+ return NULL;
+
+ info = talloc( mem_ctx, CacUserInfo );
+ if ( !info )
+ return NULL;
+
+ id21 = ctr->info.id21;
+
+ ZERO_STRUCTP( info );
+
+ info->logon_time = nt_time_to_unix( id21->logon_time );
+ info->logoff_time = nt_time_to_unix( id21->logoff_time );
+ info->kickoff_time = nt_time_to_unix( id21->kickoff_time );
+ info->pass_last_set_time =
+ nt_time_to_unix( id21->pass_last_set_time );
+ info->pass_can_change_time =
+ nt_time_to_unix( id21->pass_can_change_time );
+ info->pass_must_change_time =
+ nt_time_to_unix( id21->pass_must_change_time );
+
+ info->username =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_user_name );
+ if ( !info->username )
+ return NULL;
+
+ info->full_name =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_full_name );
+ if ( !info->full_name )
+ return NULL;
+
+ info->home_dir =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_home_dir );
+ if ( !info->home_dir )
+ return NULL;
+
+ info->home_drive =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_dir_drive );
+ if ( !info->home_drive )
+ return NULL;
+
+ info->logon_script =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_logon_script );
+ if ( !info->logon_script )
+ return NULL;
+
+ info->profile_path =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_profile_path );
+ if ( !info->profile_path )
+ return NULL;
+
+ info->description =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_acct_desc );
+ if ( !info->description )
+ return NULL;
+
+ info->workstations =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_workstations );
+ if ( !info->workstations )
+ return NULL;
+
+ info->dial =
+ talloc_unistr2_to_ascii( mem_ctx, id21->uni_munged_dial );
+ if ( !info->dial )
+ return NULL;
+
+ info->rid = id21->user_rid;
+ info->group_rid = id21->group_rid;
+ info->acb_mask = id21->acb_info;
+ info->bad_passwd_count = id21->bad_password_count;
+ info->logon_count = id21->logon_count;
+
+ memcpy( info->nt_password, id21->nt_pwd, 8 );
+ memcpy( info->lm_password, id21->lm_pwd, 8 );
+
+ info->logon_hours =
+ ( LOGON_HRS * ) talloc_memdup( mem_ctx, &( id21->logon_hrs ),
+ sizeof( LOGON_HRS ) );
+ if ( !info->logon_hours )
+ return NULL;
+
+ info->pass_must_change = ( id21->passmustchange ) ? True : False;
+
+ return info;
}
-CacAliasInfo *cac_MakeAliasInfo(TALLOC_CTX *mem_ctx, ALIAS_INFO_CTR ctr) {
- CacGroupInfo *info = NULL;
+CacGroupInfo *cac_MakeGroupInfo( TALLOC_CTX * mem_ctx, GROUP_INFO_CTR * ctr )
+{
+ CacGroupInfo *info = NULL;
- if(!mem_ctx || ctr.level != 1)
- return NULL;
+ if ( !mem_ctx || !ctr || ctr->switch_value1 != 1 )
+ return NULL;
- info = talloc(mem_ctx, CacAliasInfo);
- if(!info)
- return NULL;
+ info = talloc( mem_ctx, CacGroupInfo );
+ if ( !info )
+ return NULL;
- info->name = talloc_unistr2_to_ascii(mem_ctx, *(ctr.alias.info1.name.string));
- if(!info->name)
- return NULL;
+ info->name =
+ talloc_unistr2_to_ascii( mem_ctx,
+ ctr->group.info1.uni_acct_name );
+ if ( !info->name )
+ return NULL;
- info->description = talloc_unistr2_to_ascii(mem_ctx, *(ctr.alias.info1.description.string));
- if(!info->name)
- return NULL;
+ info->description =
+ talloc_unistr2_to_ascii( mem_ctx,
+ ctr->group.info1.uni_acct_desc );
+ if ( !info->description )
+ return NULL;
- info->num_members = ctr.alias.info1.num_member;
+ info->num_members = ctr->group.info1.num_members;
- return info;
+ return info;
}
-ALIAS_INFO_CTR *cac_MakeAliasInfoCtr(TALLOC_CTX *mem_ctx, CacAliasInfo *info) {
- ALIAS_INFO_CTR *ctr = NULL;
+GROUP_INFO_CTR *cac_MakeGroupInfoCtr( TALLOC_CTX * mem_ctx,
+ CacGroupInfo * info )
+{
+ GROUP_INFO_CTR *ctr = NULL;
- if(!mem_ctx || !info)
- return NULL;
+ if ( !mem_ctx || !info )
+ return NULL;
- ctr = talloc(mem_ctx, ALIAS_INFO_CTR);
- if(!ctr)
- return NULL;
+ ctr = talloc( mem_ctx, GROUP_INFO_CTR );
+ if ( !ctr )
+ return NULL;
- ctr->level = 1;
+ ctr->switch_value1 = 1;
- init_samr_alias_info1(&(ctr->alias.info1), info->name, info->num_members, info->description);
+ init_samr_group_info1( &( ctr->group.info1 ), info->name,
+ info->description, info->num_members );
- return ctr;
+ return ctr;
}
-CacDomainInfo *cac_MakeDomainInfo(TALLOC_CTX *mem_ctx, SAM_UNK_INFO_1 *info1, SAM_UNK_INFO_2 *info2, SAM_UNK_INFO_12 *info12) {
- CacDomainInfo *info = NULL;
-
- if(!mem_ctx || !info1 || !info2 || !info12)
- return NULL;
-
- info = talloc(mem_ctx, CacDomainInfo);
- if(!info)
- return NULL;
+CacAliasInfo *cac_MakeAliasInfo( TALLOC_CTX * mem_ctx, ALIAS_INFO_CTR ctr )
+{
+ CacGroupInfo *info = NULL;
- info->min_pass_length = info1->min_length_password;
- info->pass_history = info1->password_history;
+ if ( !mem_ctx || ctr.level != 1 )
+ return NULL;
- cac_InitCacTime(&(info->expire), info1->expire);
- cac_InitCacTime(&(info->min_pass_age), info1->min_passwordage);
+ info = talloc( mem_ctx, CacAliasInfo );
+ if ( !info )
+ return NULL;
- info->server_role = info2->server_role;
- info->num_users = info2->num_domain_usrs;
- info->num_domain_groups = info2->num_domain_grps;
- info->num_local_groups = info2->num_local_grps;
+ info->name =
+ talloc_unistr2_to_ascii( mem_ctx,
+ *( ctr.alias.info1.name.string ) );
+ if ( !info->name )
+ return NULL;
- /*if these have been ZERO'd out we need to know. uni_str_len will be 0*/
- if(info2->uni_comment.uni_str_len == 0) {
- info->comment = talloc_strdup(mem_ctx, "\0");
- }
- else {
- info->comment = talloc_unistr2_to_ascii(mem_ctx, info2->uni_comment);
- }
+ info->description =
+ talloc_unistr2_to_ascii( mem_ctx,
+ *( ctr.alias.info1.description.
+ string ) );
+ if ( !info->name )
+ return NULL;
- if(info2->uni_domain.uni_str_len == 0) {
- info->domain_name = talloc_strdup(mem_ctx, "\0");
- }
- else {
- info->domain_name = talloc_unistr2_to_ascii(mem_ctx, info2->uni_domain);
- }
+ info->num_members = ctr.alias.info1.num_member;
- if(info2->uni_server.uni_str_len == 0) {
- info->server_name = talloc_strdup(mem_ctx, "\0");
- }
- else {
- info->server_name = talloc_unistr2_to_ascii(mem_ctx, info2->uni_server);
- }
-
-
- cac_InitCacTime(&(info->lockout_duration), info12->duration);
- cac_InitCacTime(&(info->lockout_reset), info12->reset_count);
- info->num_bad_attempts = info12->bad_attempt_lockout;
-
- return info;
+ return info;
}
-char *cac_unistr_ascii(TALLOC_CTX *mem_ctx, UNISTR src) {
- char *buf;
- uint32 len;
+ALIAS_INFO_CTR *cac_MakeAliasInfoCtr( TALLOC_CTX * mem_ctx,
+ CacAliasInfo * info )
+{
+ ALIAS_INFO_CTR *ctr = NULL;
- if(!mem_ctx || !src.buffer)
- return NULL;
+ if ( !mem_ctx || !info )
+ return NULL;
- len = unistrlen(src.buffer) + 1;
+ ctr = talloc( mem_ctx, ALIAS_INFO_CTR );
+ if ( !ctr )
+ return NULL;
- buf = TALLOC_ZERO_ARRAY(mem_ctx, char, len);
- if(!buf)
- return NULL;
+ ctr->level = 1;
- rpcstr_pull(buf, src.buffer, len, -1, STR_TERMINATE);
+ init_samr_alias_info1( &( ctr->alias.info1 ), info->name,
+ info->num_members, info->description );
- return buf;
+ return ctr;
}
-CacService *cac_MakeServiceArray(TALLOC_CTX *mem_ctx, ENUM_SERVICES_STATUS *svc, uint32 num_services) {
- int i;
- CacService *services = NULL;
+CacDomainInfo *cac_MakeDomainInfo( TALLOC_CTX * mem_ctx,
+ SAM_UNK_INFO_1 * info1,
+ SAM_UNK_INFO_2 * info2,
+ SAM_UNK_INFO_12 * info12 )
+{
+ CacDomainInfo *info = NULL;
+
+ if ( !mem_ctx || !info1 || !info2 || !info12 )
+ return NULL;
+
+ info = talloc( mem_ctx, CacDomainInfo );
+ if ( !info )
+ return NULL;
+
+ info->min_pass_length = info1->min_length_password;
+ info->pass_history = info1->password_history;
+
+ cac_InitCacTime( &( info->expire ), info1->expire );
+ cac_InitCacTime( &( info->min_pass_age ), info1->min_passwordage );
+
+ info->server_role = info2->server_role;
+ info->num_users = info2->num_domain_usrs;
+ info->num_domain_groups = info2->num_domain_grps;
+ info->num_local_groups = info2->num_local_grps;
+
+ /*if these have been ZERO'd out we need to know. uni_str_len will be 0 */
+ if ( info2->uni_comment.uni_str_len == 0 ) {
+ info->comment = talloc_strdup( mem_ctx, "\0" );
+ } else {
+ info->comment =
+ talloc_unistr2_to_ascii( mem_ctx,
+ info2->uni_comment );
+ }
+
+ if ( info2->uni_domain.uni_str_len == 0 ) {
+ info->domain_name = talloc_strdup( mem_ctx, "\0" );
+ } else {
+ info->domain_name =
+ talloc_unistr2_to_ascii( mem_ctx, info2->uni_domain );
+ }
+
+ if ( info2->uni_server.uni_str_len == 0 ) {
+ info->server_name = talloc_strdup( mem_ctx, "\0" );
+ } else {
+ info->server_name =
+ talloc_unistr2_to_ascii( mem_ctx, info2->uni_server );
+ }
+
+
+ cac_InitCacTime( &( info->lockout_duration ), info12->duration );
+ cac_InitCacTime( &( info->lockout_reset ), info12->reset_count );
+ info->num_bad_attempts = info12->bad_attempt_lockout;
+
+ return info;
+}
- if(!mem_ctx || !svc)
- return NULL;
+char *cac_unistr_ascii( TALLOC_CTX * mem_ctx, UNISTR src )
+{
+ char *buf;
+ uint32 len;
- services = TALLOC_ZERO_ARRAY(mem_ctx, CacService, num_services);
- if(!services)
- return NULL;
+ if ( !mem_ctx || !src.buffer )
+ return NULL;
- for(i = 0; i < num_services; i++) {
- services[i].service_name = cac_unistr_ascii(mem_ctx, svc[i].servicename);
- services[i].display_name = cac_unistr_ascii(mem_ctx, svc[i].displayname);
+ len = unistrlen( src.buffer ) + 1;
- if(!services[i].service_name || !services[i].display_name)
- return NULL;
+ buf = TALLOC_ZERO_ARRAY( mem_ctx, char, len );
+ if ( !buf )
+ return NULL;
- services[i].status = svc[i].status;
- }
+ rpcstr_pull( buf, src.buffer, len, -1, STR_TERMINATE );
- return services;
+ return buf;
}
-int cac_InitCacServiceConfig(TALLOC_CTX *mem_ctx, SERVICE_CONFIG *src, CacServiceConfig *dest) {
- if(!src || !dest)
- return CAC_FAILURE;
+CacService *cac_MakeServiceArray( TALLOC_CTX * mem_ctx,
+ ENUM_SERVICES_STATUS * svc,
+ uint32 num_services )
+{
+ int i;
+ CacService *services = NULL;
- dest->exe_path = talloc_unistr2_to_ascii(mem_ctx, *src->executablepath);
- if(!dest->exe_path)
- return CAC_FAILURE;
+ if ( !mem_ctx || !svc )
+ return NULL;
- dest->load_order_group = talloc_unistr2_to_ascii(mem_ctx, *src->loadordergroup);
- if(!dest->load_order_group)
- return CAC_FAILURE;
+ services = TALLOC_ZERO_ARRAY( mem_ctx, CacService, num_services );
+ if ( !services )
+ return NULL;
- dest->dependencies = talloc_unistr2_to_ascii(mem_ctx, *src->dependencies);
- if(!dest->dependencies)
- return CAC_FAILURE;
+ for ( i = 0; i < num_services; i++ ) {
+ services[i].service_name =
+ cac_unistr_ascii( mem_ctx, svc[i].servicename );
+ services[i].display_name =
+ cac_unistr_ascii( mem_ctx, svc[i].displayname );
- dest->start_name = talloc_unistr2_to_ascii(mem_ctx, *src->startname);
- if(!dest->start_name)
- return CAC_FAILURE;
+ if ( !services[i].service_name || !services[i].display_name )
+ return NULL;
- dest->display_name = talloc_unistr2_to_ascii(mem_ctx, *src->displayname);
- if(!dest->display_name)
- return CAC_FAILURE;
+ services[i].status = svc[i].status;
+ }
- dest->type = src->service_type;
- dest->start_type = src->start_type;
- dest->error_control = src->error_control;
- dest->tag_id = src->tag_id;
+ return services;
+}
- return CAC_SUCCESS;
+int cac_InitCacServiceConfig( TALLOC_CTX * mem_ctx, SERVICE_CONFIG * src,
+ CacServiceConfig * dest )
+{
+ if ( !src || !dest )
+ return CAC_FAILURE;
+
+ dest->exe_path =
+ talloc_unistr2_to_ascii( mem_ctx, *src->executablepath );
+ if ( !dest->exe_path )
+ return CAC_FAILURE;
+
+ dest->load_order_group =
+ talloc_unistr2_to_ascii( mem_ctx, *src->loadordergroup );
+ if ( !dest->load_order_group )
+ return CAC_FAILURE;
+
+ dest->dependencies =
+ talloc_unistr2_to_ascii( mem_ctx, *src->dependencies );
+ if ( !dest->dependencies )
+ return CAC_FAILURE;
+
+ dest->start_name =
+ talloc_unistr2_to_ascii( mem_ctx, *src->startname );
+ if ( !dest->start_name )
+ return CAC_FAILURE;
+
+ dest->display_name =
+ talloc_unistr2_to_ascii( mem_ctx, *src->displayname );
+ if ( !dest->display_name )
+ return CAC_FAILURE;
+
+ dest->type = src->service_type;
+ dest->start_type = src->start_type;
+ dest->error_control = src->error_control;
+ dest->tag_id = src->tag_id;
+
+ return CAC_SUCCESS;
}
diff --git a/source/librpc/gen_ndr/cli_wkssvc.c b/source/librpc/gen_ndr/cli_wkssvc.c
new file mode 100644
index 00000000000..918851a15e2
--- /dev/null
+++ b/source/librpc/gen_ndr/cli_wkssvc.c
@@ -0,0 +1,964 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * client auto-generated by pidl. DO NOT MODIFY!
+ */
+
+#include "includes.h"
+#include "librpc/gen_ndr/cli_wkssvc.h"
+
+NTSTATUS rpccli_wkssvc_NetWkstaGetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union wkssvc_NetWkstaInfo *info)
+{
+ struct wkssvc_NetWkstaGetInfo r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaGetInfo, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETWKSTAGETINFO, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetWkstaGetInfo, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetWkstaGetInfo);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaGetInfo, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+ *info = *r.out.info;
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetWkstaSetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union wkssvc_NetWkstaInfo *info, uint32_t *parm_error)
+{
+ struct wkssvc_NetWkstaSetInfo r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.info = info;
+ r.in.parm_error = parm_error;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaSetInfo, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETWKSTASETINFO, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetWkstaSetInfo, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetWkstaSetInfo);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaSetInfo, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+ *parm_error = *r.out.parm_error;
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetWkstaEnumUsers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union WKS_USER_ENUM_UNION *users, uint32_t prefmaxlen, uint32_t *entriesread, uint32_t *totalentries, uint32_t *resumehandle)
+{
+ struct wkssvc_NetWkstaEnumUsers r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.users = users;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resumehandle = resumehandle;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaEnumUsers, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETWKSTAENUMUSERS, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetWkstaEnumUsers, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetWkstaEnumUsers);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaEnumUsers, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+ *users = *r.out.users;
+ if ( entriesread ) {
+ *entriesread = *r.out.entriesread;
+ }
+ if ( totalentries ) {
+ *totalentries = *r.out.totalentries;
+ }
+ *resumehandle = *r.out.resumehandle;
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRWKSTAUSERGETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRWKSTAUSERGETINFO r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTAUSERGETINFO, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRWKSTAUSERGETINFO, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRWKSTAUSERGETINFO, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRWKSTAUSERGETINFO);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTAUSERGETINFO, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRWKSTAUSERSETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRWKSTAUSERSETINFO r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTAUSERSETINFO, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRWKSTAUSERSETINFO, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRWKSTAUSERSETINFO, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRWKSTAUSERSETINFO);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTAUSERSETINFO, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetWkstaTransportEnum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t *level, union wkssvc_NetWkstaTransportCtr *ctr, uint32_t max_buffer, uint32_t *totalentries, uint32_t *resume_handle)
+{
+ struct wkssvc_NetWkstaTransportEnum r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.ctr = ctr;
+ r.in.max_buffer = max_buffer;
+ r.in.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaTransportEnum, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETWKSTATRANSPORTENUM, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetWkstaTransportEnum, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetWkstaTransportEnum);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaTransportEnum, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+ *level = *r.out.level;
+ *ctr = *r.out.ctr;
+ if ( totalentries ) {
+ *totalentries = *r.out.totalentries;
+ }
+ *resume_handle = *r.out.resume_handle;
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRWKSTATRANSPORTADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRWKSTATRANSPORTADD r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTATRANSPORTADD, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRWKSTATRANSPORTADD, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRWKSTATRANSPORTADD, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRWKSTATRANSPORTADD);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTATRANSPORTADD, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRWKSTATRANSPORTDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRWKSTATRANSPORTDEL r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTATRANSPORTDEL, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRWKSTATRANSPORTDEL, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRWKSTATRANSPORTDEL, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRWKSTATRANSPORTDEL);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTATRANSPORTDEL, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRUSEADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRUSEADD r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEADD, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUSEADD, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRUSEADD, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRUSEADD);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEADD, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRUSEGETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRUSEGETINFO r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEGETINFO, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUSEGETINFO, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRUSEGETINFO, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRUSEGETINFO);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEGETINFO, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRUSEDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRUSEDEL r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEDEL, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUSEDEL, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRUSEDEL, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRUSEDEL);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEDEL, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRUSEENUM(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRUSEENUM r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEENUM, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUSEENUM, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRUSEENUM, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRUSEENUM);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEENUM, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRMESSAGEBUFFERSEND(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRMESSAGEBUFFERSEND r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRMESSAGEBUFFERSEND, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRMESSAGEBUFFERSEND, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRMESSAGEBUFFERSEND, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRMESSAGEBUFFERSEND);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRMESSAGEBUFFERSEND, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRWORKSTATIONSTATISTICSGET r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWORKSTATIONSTATISTICSGET, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRWORKSTATIONSTATISTICSGET, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRWORKSTATIONSTATISTICSGET, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRWORKSTATIONSTATISTICSGET);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWORKSTATIONSTATISTICSGET, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRLOGONDOMAINNAMEADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRLOGONDOMAINNAMEADD r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEADD, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRLOGONDOMAINNAMEADD, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEADD, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRLOGONDOMAINNAMEADD);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEADD, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRLOGONDOMAINNAMEDEL r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEDEL, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRLOGONDOMAINNAMEDEL, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEDEL, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRLOGONDOMAINNAMEDEL);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEDEL, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRJOINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRJOINDOMAIN r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRJOINDOMAIN, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRJOINDOMAIN, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRJOINDOMAIN, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRJOINDOMAIN);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRJOINDOMAIN, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRUNJOINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRUNJOINDOMAIN r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUNJOINDOMAIN, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUNJOINDOMAIN, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRUNJOINDOMAIN, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRUNJOINDOMAIN);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUNJOINDOMAIN, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRRENAMEMACHINEINDOMAIN r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRRENAMEMACHINEINDOMAIN, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRRENAMEMACHINEINDOMAIN, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRRENAMEMACHINEINDOMAIN);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRRENAMEMACHINEINDOMAIN, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRVALIDATENAME(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRVALIDATENAME r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRVALIDATENAME, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRVALIDATENAME, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRVALIDATENAME, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRVALIDATENAME);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRVALIDATENAME, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRGETJOININFORMATION(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRGETJOININFORMATION r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOININFORMATION, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRGETJOININFORMATION, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRGETJOININFORMATION, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRGETJOININFORMATION);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOININFORMATION, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRGETJOINABLEOUS(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRGETJOINABLEOUS r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOINABLEOUS, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRGETJOINABLEOUS, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRGETJOINABLEOUS, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRGETJOINABLEOUS);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOINABLEOUS, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetrJoinDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *domain_name, const char *account_name, const char *admin_account, struct wkssvc_PasswordBuffer *encrypted_password, uint32_t join_flags)
+{
+ struct wkssvc_NetrJoinDomain2 r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.domain_name = domain_name;
+ r.in.account_name = account_name;
+ r.in.admin_account = admin_account;
+ r.in.encrypted_password = encrypted_password;
+ r.in.join_flags = join_flags;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrJoinDomain2, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRJOINDOMAIN2, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetrJoinDomain2, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetrJoinDomain2);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrJoinDomain2, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetrUnjoinDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *account, struct wkssvc_PasswordBuffer *encrypted_password, uint32_t unjoin_flags)
+{
+ struct wkssvc_NetrUnjoinDomain2 r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.account = account;
+ r.in.encrypted_password = encrypted_password;
+ r.in.unjoin_flags = unjoin_flags;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrUnjoinDomain2, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRUNJOINDOMAIN2, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetrUnjoinDomain2, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetrUnjoinDomain2);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrUnjoinDomain2, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetrRenameMachineInDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *NewMachineName, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t RenameOptions)
+{
+ struct wkssvc_NetrRenameMachineInDomain2 r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.NewMachineName = NewMachineName;
+ r.in.Account = Account;
+ r.in.EncryptedPassword = EncryptedPassword;
+ r.in.RenameOptions = RenameOptions;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrRenameMachineInDomain2, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN2, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetrRenameMachineInDomain2, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetrRenameMachineInDomain2);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrRenameMachineInDomain2, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRVALIDATENAME2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRVALIDATENAME2 r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRVALIDATENAME2, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRVALIDATENAME2, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRVALIDATENAME2, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRVALIDATENAME2);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRVALIDATENAME2, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRGETJOINABLEOUS2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRGETJOINABLEOUS2 r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOINABLEOUS2, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRGETJOINABLEOUS2, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRGETJOINABLEOUS2, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRGETJOINABLEOUS2);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOINABLEOUS2, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetrAddAlternateComputerName(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *NewAlternateMachineName, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t Reserved)
+{
+ struct wkssvc_NetrAddAlternateComputerName r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.NewAlternateMachineName = NewAlternateMachineName;
+ r.in.Account = Account;
+ r.in.EncryptedPassword = EncryptedPassword;
+ r.in.Reserved = Reserved;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrAddAlternateComputerName, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRADDALTERNATECOMPUTERNAME, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetrAddAlternateComputerName, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetrAddAlternateComputerName);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrAddAlternateComputerName, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_wkssvc_NetrRemoveAlternateComputerName(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *AlternateMachineNameToRemove, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t Reserved)
+{
+ struct wkssvc_NetrRemoveAlternateComputerName r;
+ NTSTATUS status;
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.AlternateMachineNameToRemove = AlternateMachineNameToRemove;
+ r.in.Account = Account;
+ r.in.EncryptedPassword = EncryptedPassword;
+ r.in.Reserved = Reserved;
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrRemoveAlternateComputerName, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRREMOVEALTERNATECOMPUTERNAME, &r, (ndr_pull_flags_fn_t)ndr_pull_wkssvc_NetrRemoveAlternateComputerName, (ndr_push_flags_fn_t)ndr_push_wkssvc_NetrRemoveAlternateComputerName);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrRemoveAlternateComputerName, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRSETPRIMARYCOMPUTERNAME, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRSETPRIMARYCOMPUTERNAME, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRSETPRIMARYCOMPUTERNAME, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRSETPRIMARYCOMPUTERNAME);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRSETPRIMARYCOMPUTERNAME, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
+NTSTATUS rpccli_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ struct WKSSVC_NETRENUMERATECOMPUTERNAMES r;
+ NTSTATUS status;
+
+ /* In parameters */
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRENUMERATECOMPUTERNAMES, &r);
+
+ status = cli_do_rpc_ndr(cli, mem_ctx, PI_WKSSVC, DCERPC_WKSSVC_NETRENUMERATECOMPUTERNAMES, &r, (ndr_pull_flags_fn_t)ndr_pull_WKSSVC_NETRENUMERATECOMPUTERNAMES, (ndr_push_flags_fn_t)ndr_push_WKSSVC_NETRENUMERATECOMPUTERNAMES);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRENUMERATECOMPUTERNAMES, &r);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.out.result);
+}
+
diff --git a/source/librpc/gen_ndr/cli_wkssvc.h b/source/librpc/gen_ndr/cli_wkssvc.h
new file mode 100644
index 00000000000..1cbe0dd23e5
--- /dev/null
+++ b/source/librpc/gen_ndr/cli_wkssvc.h
@@ -0,0 +1,35 @@
+#include "librpc/gen_ndr/ndr_wkssvc.h"
+#ifndef __CLI_WKSSVC__
+#define __CLI_WKSSVC__
+NTSTATUS rpccli_wkssvc_NetWkstaGetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union wkssvc_NetWkstaInfo *info);
+NTSTATUS rpccli_wkssvc_NetWkstaSetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union wkssvc_NetWkstaInfo *info, uint32_t *parm_error);
+NTSTATUS rpccli_wkssvc_NetWkstaEnumUsers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t level, union WKS_USER_ENUM_UNION *users, uint32_t prefmaxlen, uint32_t *entriesread, uint32_t *totalentries, uint32_t *resumehandle);
+NTSTATUS rpccli_WKSSVC_NETRWKSTAUSERGETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRWKSTAUSERSETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_wkssvc_NetWkstaTransportEnum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, uint32_t *level, union wkssvc_NetWkstaTransportCtr *ctr, uint32_t max_buffer, uint32_t *totalentries, uint32_t *resume_handle);
+NTSTATUS rpccli_WKSSVC_NETRWKSTATRANSPORTADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRWKSTATRANSPORTDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRUSEADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRUSEGETINFO(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRUSEDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRUSEENUM(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRMESSAGEBUFFERSEND(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRLOGONDOMAINNAMEADD(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRJOINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRUNJOINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRVALIDATENAME(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRGETJOININFORMATION(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRGETJOINABLEOUS(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_wkssvc_NetrJoinDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *domain_name, const char *account_name, const char *admin_account, struct wkssvc_PasswordBuffer *encrypted_password, uint32_t join_flags);
+NTSTATUS rpccli_wkssvc_NetrUnjoinDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *account, struct wkssvc_PasswordBuffer *encrypted_password, uint32_t unjoin_flags);
+NTSTATUS rpccli_wkssvc_NetrRenameMachineInDomain2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *NewMachineName, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t RenameOptions);
+NTSTATUS rpccli_WKSSVC_NETRVALIDATENAME2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRGETJOINABLEOUS2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_wkssvc_NetrAddAlternateComputerName(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *NewAlternateMachineName, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t Reserved);
+NTSTATUS rpccli_wkssvc_NetrRemoveAlternateComputerName(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *server_name, const char *AlternateMachineNameToRemove, const char *Account, struct wkssvc_PasswordBuffer *EncryptedPassword, uint32_t Reserved);
+NTSTATUS rpccli_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+NTSTATUS rpccli_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx);
+#endif /* __CLI_WKSSVC__ */
diff --git a/source/librpc/gen_ndr/ndr_notify.c b/source/librpc/gen_ndr/ndr_notify.c
new file mode 100644
index 00000000000..c3873550bb0
--- /dev/null
+++ b/source/librpc/gen_ndr/ndr_notify.c
@@ -0,0 +1,242 @@
+/* parser auto-generated by pidl */
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_notify.h"
+
+_PUBLIC_ NTSTATUS ndr_push_notify_entry(struct ndr_push *ndr, int ndr_flags, const struct notify_entry *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_server_id(ndr, NDR_SCALARS, &r->server));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->filter));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->subdir_filter));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->path));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->path_len));
+ NDR_CHECK(ndr_push_pointer(ndr, NDR_SCALARS, r->private_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_server_id(ndr, NDR_BUFFERS, &r->server));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS ndr_pull_notify_entry(struct ndr_pull *ndr, int ndr_flags, struct notify_entry *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_server_id(ndr, NDR_SCALARS, &r->server));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->filter));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->subdir_filter));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->path));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->path_len));
+ NDR_CHECK(ndr_pull_pointer(ndr, NDR_SCALARS, &r->private_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_server_id(ndr, NDR_BUFFERS, &r->server));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_notify_entry(struct ndr_print *ndr, const char *name, const struct notify_entry *r)
+{
+ ndr_print_struct(ndr, name, "notify_entry");
+ ndr->depth++;
+ ndr_print_server_id(ndr, "server", &r->server);
+ ndr_print_uint32(ndr, "filter", r->filter);
+ ndr_print_uint32(ndr, "subdir_filter", r->subdir_filter);
+ ndr_print_string(ndr, "path", r->path);
+ ndr_print_uint32(ndr, "path_len", r->path_len);
+ ndr_print_pointer(ndr, "private_data", r->private_data);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_notify_depth(struct ndr_push *ndr, int ndr_flags, const struct notify_depth *r)
+{
+ uint32_t cntr_entries_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_mask));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_mask_subdir));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_entries));
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_push_notify_entry(ndr, NDR_SCALARS, &r->entries[cntr_entries_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_push_notify_entry(ndr, NDR_BUFFERS, &r->entries[cntr_entries_0]));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_notify_depth(struct ndr_pull *ndr, int ndr_flags, struct notify_depth *r)
+{
+ uint32_t cntr_entries_0;
+ TALLOC_CTX *_mem_save_entries_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_mask));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_mask_subdir));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_entries));
+ NDR_PULL_ALLOC_N(ndr, r->entries, r->num_entries);
+ _mem_save_entries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_pull_notify_entry(ndr, NDR_SCALARS, &r->entries[cntr_entries_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_0, 0);
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ _mem_save_entries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->entries, 0);
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_pull_notify_entry(ndr, NDR_BUFFERS, &r->entries[cntr_entries_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entries_0, 0);
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_notify_depth(struct ndr_print *ndr, const char *name, const struct notify_depth *r)
+{
+ uint32_t cntr_entries_0;
+ ndr_print_struct(ndr, name, "notify_depth");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "max_mask", r->max_mask);
+ ndr_print_uint32(ndr, "max_mask_subdir", r->max_mask_subdir);
+ ndr_print_uint32(ndr, "num_entries", r->num_entries);
+ ndr->print(ndr, "%s: ARRAY(%d)", "entries", r->num_entries);
+ ndr->depth++;
+ for (cntr_entries_0=0;cntr_entries_0<r->num_entries;cntr_entries_0++) {
+ char *idx_0=NULL;
+ asprintf(&idx_0, "[%d]", cntr_entries_0);
+ if (idx_0) {
+ ndr_print_notify_entry(ndr, "entries", &r->entries[cntr_entries_0]);
+ free(idx_0);
+ }
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+_PUBLIC_ NTSTATUS ndr_push_notify_array(struct ndr_push *ndr, int ndr_flags, const struct notify_array *r)
+{
+ uint32_t cntr_depth_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_depths));
+ for (cntr_depth_0 = 0; cntr_depth_0 < r->num_depths; cntr_depth_0++) {
+ NDR_CHECK(ndr_push_notify_depth(ndr, NDR_SCALARS, &r->depth[cntr_depth_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ for (cntr_depth_0 = 0; cntr_depth_0 < r->num_depths; cntr_depth_0++) {
+ NDR_CHECK(ndr_push_notify_depth(ndr, NDR_BUFFERS, &r->depth[cntr_depth_0]));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS ndr_pull_notify_array(struct ndr_pull *ndr, int ndr_flags, struct notify_array *r)
+{
+ uint32_t cntr_depth_0;
+ TALLOC_CTX *_mem_save_depth_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_depths));
+ NDR_PULL_ALLOC_N(ndr, r->depth, r->num_depths);
+ _mem_save_depth_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->depth, 0);
+ for (cntr_depth_0 = 0; cntr_depth_0 < r->num_depths; cntr_depth_0++) {
+ NDR_CHECK(ndr_pull_notify_depth(ndr, NDR_SCALARS, &r->depth[cntr_depth_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_depth_0, 0);
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ _mem_save_depth_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->depth, 0);
+ for (cntr_depth_0 = 0; cntr_depth_0 < r->num_depths; cntr_depth_0++) {
+ NDR_CHECK(ndr_pull_notify_depth(ndr, NDR_BUFFERS, &r->depth[cntr_depth_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_depth_0, 0);
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_notify_array(struct ndr_print *ndr, const char *name, const struct notify_array *r)
+{
+ uint32_t cntr_depth_0;
+ ndr_print_struct(ndr, name, "notify_array");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "num_depths", r->num_depths);
+ ndr->print(ndr, "%s: ARRAY(%d)", "depth", r->num_depths);
+ ndr->depth++;
+ for (cntr_depth_0=0;cntr_depth_0<r->num_depths;cntr_depth_0++) {
+ char *idx_0=NULL;
+ asprintf(&idx_0, "[%d]", cntr_depth_0);
+ if (idx_0) {
+ ndr_print_notify_depth(ndr, "depth", &r->depth[cntr_depth_0]);
+ free(idx_0);
+ }
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+_PUBLIC_ NTSTATUS ndr_push_notify_event(struct ndr_push *ndr, int ndr_flags, const struct notify_event *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->action));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->path));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_push_pointer(ndr, NDR_SCALARS, r->private_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS ndr_pull_notify_event(struct ndr_pull *ndr, int ndr_flags, struct notify_event *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->action));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->path));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_pull_pointer(ndr, NDR_SCALARS, &r->private_data));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_notify_event(struct ndr_print *ndr, const char *name, const struct notify_event *r)
+{
+ ndr_print_struct(ndr, name, "notify_event");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "action", r->action);
+ ndr_print_string(ndr, "path", r->path);
+ ndr_print_pointer(ndr, "private_data", r->private_data);
+ ndr->depth--;
+}
+
diff --git a/source/librpc/gen_ndr/ndr_notify.h b/source/librpc/gen_ndr/ndr_notify.h
new file mode 100644
index 00000000000..793ffa51ca7
--- /dev/null
+++ b/source/librpc/gen_ndr/ndr_notify.h
@@ -0,0 +1,20 @@
+/* header auto-generated by pidl */
+
+#include "librpc/gen_ndr/notify.h"
+
+#ifndef _HEADER_NDR_notify
+#define _HEADER_NDR_notify
+
+#include "librpc/ndr/libndr.h"
+#define DCERPC_NOTIFY_CALL_COUNT (0)
+NTSTATUS ndr_push_notify_entry(struct ndr_push *ndr, int ndr_flags, const struct notify_entry *r);
+NTSTATUS ndr_pull_notify_entry(struct ndr_pull *ndr, int ndr_flags, struct notify_entry *r);
+void ndr_print_notify_entry(struct ndr_print *ndr, const char *name, const struct notify_entry *r);
+void ndr_print_notify_depth(struct ndr_print *ndr, const char *name, const struct notify_depth *r);
+NTSTATUS ndr_push_notify_array(struct ndr_push *ndr, int ndr_flags, const struct notify_array *r);
+NTSTATUS ndr_pull_notify_array(struct ndr_pull *ndr, int ndr_flags, struct notify_array *r);
+void ndr_print_notify_array(struct ndr_print *ndr, const char *name, const struct notify_array *r);
+NTSTATUS ndr_push_notify_event(struct ndr_push *ndr, int ndr_flags, const struct notify_event *r);
+NTSTATUS ndr_pull_notify_event(struct ndr_pull *ndr, int ndr_flags, struct notify_event *r);
+void ndr_print_notify_event(struct ndr_print *ndr, const char *name, const struct notify_event *r);
+#endif /* _HEADER_NDR_notify */
diff --git a/source/librpc/gen_ndr/ndr_srvsvc.h b/source/librpc/gen_ndr/ndr_srvsvc.h
new file mode 100644
index 00000000000..090d14beb87
--- /dev/null
+++ b/source/librpc/gen_ndr/ndr_srvsvc.h
@@ -0,0 +1,312 @@
+/* header auto-generated by pidl */
+
+#include "librpc/gen_ndr/srvsvc.h"
+
+#ifndef _HEADER_NDR_srvsvc
+#define _HEADER_NDR_srvsvc
+
+#include "librpc/ndr/libndr.h"
+#define DCERPC_SRVSVC_UUID "4b324fc8-1670-01d3-1278-5a47bf6ee188"
+#define DCERPC_SRVSVC_VERSION 3.0
+#define DCERPC_SRVSVC_NAME "srvsvc"
+#define DCERPC_SRVSVC_HELPSTRING "Server Service"
+extern const struct dcerpc_interface_table dcerpc_table_srvsvc;
+NTSTATUS dcerpc_server_srvsvc_init(void);
+#define DCERPC_SRVSVC_NETCHARDEVENUM (0x00)
+
+#define DCERPC_SRVSVC_NETCHARDEVGETINFO (0x01)
+
+#define DCERPC_SRVSVC_NETCHARDEVCONTROL (0x02)
+
+#define DCERPC_SRVSVC_NETCHARDEVQENUM (0x03)
+
+#define DCERPC_SRVSVC_NETCHARDEVQGETINFO (0x04)
+
+#define DCERPC_SRVSVC_NETCHARDEVQSETINFO (0x05)
+
+#define DCERPC_SRVSVC_NETCHARDEVQPURGE (0x06)
+
+#define DCERPC_SRVSVC_NETCHARDEVQPURGESELF (0x07)
+
+#define DCERPC_SRVSVC_NETCONNENUM (0x08)
+
+#define DCERPC_SRVSVC_NETFILEENUM (0x09)
+
+#define DCERPC_SRVSVC_NETFILEGETINFO (0x0a)
+
+#define DCERPC_SRVSVC_NETFILECLOSE (0x0b)
+
+#define DCERPC_SRVSVC_NETSESSENUM (0x0c)
+
+#define DCERPC_SRVSVC_NETSESSDEL (0x0d)
+
+#define DCERPC_SRVSVC_NETSHAREADD (0x0e)
+
+#define DCERPC_SRVSVC_NETSHAREENUMALL (0x0f)
+
+#define DCERPC_SRVSVC_NETSHAREGETINFO (0x10)
+
+#define DCERPC_SRVSVC_NETSHARESETINFO (0x11)
+
+#define DCERPC_SRVSVC_NETSHAREDEL (0x12)
+
+#define DCERPC_SRVSVC_NETSHAREDELSTICKY (0x13)
+
+#define DCERPC_SRVSVC_NETSHARECHECK (0x14)
+
+#define DCERPC_SRVSVC_NETSRVGETINFO (0x15)
+
+#define DCERPC_SRVSVC_NETSRVSETINFO (0x16)
+
+#define DCERPC_SRVSVC_NETDISKENUM (0x17)
+
+#define DCERPC_SRVSVC_NETSERVERSTATISTICSGET (0x18)
+
+#define DCERPC_SRVSVC_NETTRANSPORTADD (0x19)
+
+#define DCERPC_SRVSVC_NETTRANSPORTENUM (0x1a)
+
+#define DCERPC_SRVSVC_NETTRANSPORTDEL (0x1b)
+
+#define DCERPC_SRVSVC_NETREMOTETOD (0x1c)
+
+#define DCERPC_SRVSVC_NETSETSERVICEBITS (0x1d)
+
+#define DCERPC_SRVSVC_NETPATHTYPE (0x1e)
+
+#define DCERPC_SRVSVC_NETPATHCANONICALIZE (0x1f)
+
+#define DCERPC_SRVSVC_NETPATHCOMPARE (0x20)
+
+#define DCERPC_SRVSVC_NETNAMEVALIDATE (0x21)
+
+#define DCERPC_SRVSVC_NETRPRNAMECANONICALIZE (0x22)
+
+#define DCERPC_SRVSVC_NETPRNAMECOMPARE (0x23)
+
+#define DCERPC_SRVSVC_NETSHAREENUM (0x24)
+
+#define DCERPC_SRVSVC_NETSHAREDELSTART (0x25)
+
+#define DCERPC_SRVSVC_NETSHAREDELCOMMIT (0x26)
+
+#define DCERPC_SRVSVC_NETGETFILESECURITY (0x27)
+
+#define DCERPC_SRVSVC_NETSETFILESECURITY (0x28)
+
+#define DCERPC_SRVSVC_NETSERVERTRANSPORTADDEX (0x29)
+
+#define DCERPC_SRVSVC_NETSERVERSETSERVICEBITSEX (0x2a)
+
+#define DCERPC_SRVSVC_NETRDFSGETVERSION (0x2b)
+
+#define DCERPC_SRVSVC_NETRDFSCREATELOCALPARTITION (0x2c)
+
+#define DCERPC_SRVSVC_NETRDFSDELETELOCALPARTITION (0x2d)
+
+#define DCERPC_SRVSVC_NETRDFSSETLOCALVOLUMESTATE (0x2e)
+
+#define DCERPC_SRVSVC_NETRDFSSETSERVERINFO (0x2f)
+
+#define DCERPC_SRVSVC_NETRDFSCREATEEXITPOINT (0x30)
+
+#define DCERPC_SRVSVC_NETRDFSDELETEEXITPOINT (0x31)
+
+#define DCERPC_SRVSVC_NETRDFSMODIFYPREFIX (0x32)
+
+#define DCERPC_SRVSVC_NETRDFSFIXLOCALVOLUME (0x33)
+
+#define DCERPC_SRVSVC_NETRDFSMANAGERREPORTSITEINFO (0x34)
+
+#define DCERPC_SRVSVC_NETRSERVERTRANSPORTDELEX (0x35)
+
+#define DCERPC_SRVSVC_CALL_COUNT (54)
+void ndr_print_srvsvc_NetCharDevInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevInfo0 *r);
+void ndr_print_srvsvc_NetCharDevCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevCtr0 *r);
+void ndr_print_srvsvc_NetCharDevInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevInfo1 *r);
+void ndr_print_srvsvc_NetCharDevCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevCtr1 *r);
+void ndr_print_srvsvc_NetCharDevInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetCharDevInfo *r);
+void ndr_print_srvsvc_NetCharDevCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetCharDevCtr *r);
+void ndr_print_srvsvc_NetCharDevQInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevQInfo0 *r);
+void ndr_print_srvsvc_NetCharDevQCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevQCtr0 *r);
+void ndr_print_srvsvc_NetCharDevQInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevQInfo1 *r);
+void ndr_print_srvsvc_NetCharDevQCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetCharDevQCtr1 *r);
+void ndr_print_srvsvc_NetCharDevQInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetCharDevQInfo *r);
+void ndr_print_srvsvc_NetCharDevQCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetCharDevQCtr *r);
+void ndr_print_srvsvc_NetConnInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetConnInfo0 *r);
+void ndr_print_srvsvc_NetConnCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetConnCtr0 *r);
+void ndr_print_srvsvc_NetConnInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetConnInfo1 *r);
+void ndr_print_srvsvc_NetConnCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetConnCtr1 *r);
+void ndr_print_srvsvc_NetConnCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetConnCtr *r);
+void ndr_print_srvsvc_NetFileInfo2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetFileInfo2 *r);
+void ndr_print_srvsvc_NetFileCtr2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetFileCtr2 *r);
+void ndr_print_srvsvc_NetFileInfo3(struct ndr_print *ndr, const char *name, const struct srvsvc_NetFileInfo3 *r);
+void ndr_print_srvsvc_NetFileCtr3(struct ndr_print *ndr, const char *name, const struct srvsvc_NetFileCtr3 *r);
+void ndr_print_srvsvc_NetFileInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetFileInfo *r);
+void ndr_print_srvsvc_NetFileCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetFileCtr *r);
+void ndr_print_srvsvc_NetSessInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessInfo0 *r);
+void ndr_print_srvsvc_NetSessCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessCtr0 *r);
+void ndr_print_srvsvc_NetSessInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessInfo1 *r);
+void ndr_print_srvsvc_NetSessCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessCtr1 *r);
+void ndr_print_srvsvc_NetSessInfo2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessInfo2 *r);
+void ndr_print_srvsvc_NetSessCtr2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessCtr2 *r);
+void ndr_print_srvsvc_NetSessInfo10(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessInfo10 *r);
+void ndr_print_srvsvc_NetSessCtr10(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessCtr10 *r);
+void ndr_print_srvsvc_NetSessInfo502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessInfo502 *r);
+void ndr_print_srvsvc_NetSessCtr502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSessCtr502 *r);
+void ndr_print_srvsvc_NetSessCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetSessCtr *r);
+void ndr_print_srvsvc_ShareType(struct ndr_print *ndr, const char *name, enum srvsvc_ShareType r);
+void ndr_print_srvsvc_NetShareInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo0 *r);
+void ndr_print_srvsvc_NetShareCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr0 *r);
+void ndr_print_srvsvc_NetShareInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo1 *r);
+void ndr_print_srvsvc_NetShareCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1 *r);
+void ndr_print_srvsvc_NetShareInfo2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo2 *r);
+void ndr_print_srvsvc_NetShareCtr2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr2 *r);
+void ndr_print_srvsvc_NetShareInfo501(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo501 *r);
+void ndr_print_srvsvc_NetShareCtr501(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr501 *r);
+void ndr_print_srvsvc_NetShareInfo502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo502 *r);
+void ndr_print_srvsvc_NetShareCtr502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr502 *r);
+void ndr_print_srvsvc_NetShareInfo1004(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo1004 *r);
+void ndr_print_srvsvc_NetShareCtr1004(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1004 *r);
+void ndr_print_NetShareInfo1005Flags(struct ndr_print *ndr, const char *name, uint32_t r);
+void ndr_print_srvsvc_NetShareInfo1005(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo1005 *r);
+void ndr_print_srvsvc_NetShareCtr1005(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1005 *r);
+void ndr_print_srvsvc_NetShareInfo1006(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo1006 *r);
+void ndr_print_srvsvc_NetShareCtr1006(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1006 *r);
+void ndr_print_srvsvc_NetShareInfo1007(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareInfo1007 *r);
+void ndr_print_srvsvc_NetShareCtr1007(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1007 *r);
+void ndr_print_srvsvc_NetShareCtr1501(struct ndr_print *ndr, const char *name, const struct srvsvc_NetShareCtr1501 *r);
+void ndr_print_srvsvc_NetShareInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetShareInfo *r);
+void ndr_print_srvsvc_NetShareCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetShareCtr *r);
+NTSTATUS ndr_push_srvsvc_PlatformId(struct ndr_push *ndr, int ndr_flags, enum srvsvc_PlatformId r);
+NTSTATUS ndr_pull_srvsvc_PlatformId(struct ndr_pull *ndr, int ndr_flags, enum srvsvc_PlatformId *r);
+void ndr_print_srvsvc_PlatformId(struct ndr_print *ndr, const char *name, enum srvsvc_PlatformId r);
+void ndr_print_srvsvc_NetSrvInfo100(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo100 *r);
+void ndr_print_srvsvc_NetSrvInfo101(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo101 *r);
+void ndr_print_srvsvc_NetSrvInfo102(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo102 *r);
+void ndr_print_srvsvc_NetSrvInfo402(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo402 *r);
+void ndr_print_srvsvc_NetSrvInfo403(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo403 *r);
+void ndr_print_srvsvc_NetSrvInfo502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo502 *r);
+void ndr_print_srvsvc_NetSrvInfo503(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo503 *r);
+void ndr_print_srvsvc_NetSrvInfo599(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo599 *r);
+void ndr_print_srvsvc_NetSrvInfo1005(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1005 *r);
+void ndr_print_srvsvc_NetSrvInfo1010(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1010 *r);
+void ndr_print_srvsvc_NetSrvInfo1016(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1016 *r);
+void ndr_print_srvsvc_NetSrvInfo1017(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1017 *r);
+void ndr_print_srvsvc_NetSrvInfo1018(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1018 *r);
+void ndr_print_srvsvc_NetSrvInfo1107(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1107 *r);
+void ndr_print_srvsvc_NetSrvInfo1501(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1501 *r);
+void ndr_print_srvsvc_NetSrvInfo1502(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1502 *r);
+void ndr_print_srvsvc_NetSrvInfo1503(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1503 *r);
+void ndr_print_srvsvc_NetSrvInfo1506(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1506 *r);
+void ndr_print_srvsvc_NetSrvInfo1509(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1509 *r);
+void ndr_print_srvsvc_NetSrvInfo1510(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1510 *r);
+void ndr_print_srvsvc_NetSrvInfo1511(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1511 *r);
+void ndr_print_srvsvc_NetSrvInfo1512(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1512 *r);
+void ndr_print_srvsvc_NetSrvInfo1513(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1513 *r);
+void ndr_print_srvsvc_NetSrvInfo1514(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1514 *r);
+void ndr_print_srvsvc_NetSrvInfo1515(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1515 *r);
+void ndr_print_srvsvc_NetSrvInfo1516(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1516 *r);
+void ndr_print_srvsvc_NetSrvInfo1518(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1518 *r);
+void ndr_print_srvsvc_NetSrvInfo1520(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1520 *r);
+void ndr_print_srvsvc_NetSrvInfo1521(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1521 *r);
+void ndr_print_srvsvc_NetSrvInfo1522(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1522 *r);
+void ndr_print_srvsvc_NetSrvInfo1523(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1523 *r);
+void ndr_print_srvsvc_NetSrvInfo1524(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1524 *r);
+void ndr_print_srvsvc_NetSrvInfo1525(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1525 *r);
+void ndr_print_srvsvc_NetSrvInfo1528(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1528 *r);
+void ndr_print_srvsvc_NetSrvInfo1529(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1529 *r);
+void ndr_print_srvsvc_NetSrvInfo1530(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1530 *r);
+void ndr_print_srvsvc_NetSrvInfo1533(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1533 *r);
+void ndr_print_srvsvc_NetSrvInfo1534(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1534 *r);
+void ndr_print_srvsvc_NetSrvInfo1535(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1535 *r);
+void ndr_print_srvsvc_NetSrvInfo1536(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1536 *r);
+void ndr_print_srvsvc_NetSrvInfo1537(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1537 *r);
+void ndr_print_srvsvc_NetSrvInfo1538(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1538 *r);
+void ndr_print_srvsvc_NetSrvInfo1539(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1539 *r);
+void ndr_print_srvsvc_NetSrvInfo1540(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1540 *r);
+void ndr_print_srvsvc_NetSrvInfo1541(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1541 *r);
+void ndr_print_srvsvc_NetSrvInfo1542(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1542 *r);
+void ndr_print_srvsvc_NetSrvInfo1543(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1543 *r);
+void ndr_print_srvsvc_NetSrvInfo1544(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1544 *r);
+void ndr_print_srvsvc_NetSrvInfo1545(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1545 *r);
+void ndr_print_srvsvc_NetSrvInfo1546(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1546 *r);
+void ndr_print_srvsvc_NetSrvInfo1547(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1547 *r);
+void ndr_print_srvsvc_NetSrvInfo1548(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1548 *r);
+void ndr_print_srvsvc_NetSrvInfo1549(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1549 *r);
+void ndr_print_srvsvc_NetSrvInfo1550(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1550 *r);
+void ndr_print_srvsvc_NetSrvInfo1552(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1552 *r);
+void ndr_print_srvsvc_NetSrvInfo1553(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1553 *r);
+void ndr_print_srvsvc_NetSrvInfo1554(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1554 *r);
+void ndr_print_srvsvc_NetSrvInfo1555(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1555 *r);
+void ndr_print_srvsvc_NetSrvInfo1556(struct ndr_print *ndr, const char *name, const struct srvsvc_NetSrvInfo1556 *r);
+void ndr_print_srvsvc_NetSrvInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetSrvInfo *r);
+void ndr_print_srvsvc_NetDiskInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetDiskInfo0 *r);
+void ndr_print_srvsvc_NetDiskInfo(struct ndr_print *ndr, const char *name, const struct srvsvc_NetDiskInfo *r);
+void ndr_print_srvsvc_Statistics(struct ndr_print *ndr, const char *name, const struct srvsvc_Statistics *r);
+void ndr_print_srvsvc_NetTransportInfo0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportInfo0 *r);
+void ndr_print_srvsvc_NetTransportCtr0(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportCtr0 *r);
+void ndr_print_srvsvc_NetTransportInfo1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportInfo1 *r);
+void ndr_print_srvsvc_NetTransportCtr1(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportCtr1 *r);
+void ndr_print_srvsvc_NetTransportInfo2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportInfo2 *r);
+void ndr_print_srvsvc_NetTransportCtr2(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportCtr2 *r);
+void ndr_print_srvsvc_NetTransportInfo3(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportInfo3 *r);
+void ndr_print_srvsvc_NetTransportCtr3(struct ndr_print *ndr, const char *name, const struct srvsvc_NetTransportCtr3 *r);
+void ndr_print_srvsvc_NetTransportCtr(struct ndr_print *ndr, const char *name, const union srvsvc_NetTransportCtr *r);
+void ndr_print_srvsvc_NetRemoteTODInfo(struct ndr_print *ndr, const char *name, const struct srvsvc_NetRemoteTODInfo *r);
+void ndr_print_srvsvc_NetTransportInfo(struct ndr_print *ndr, const char *name, const union srvsvc_NetTransportInfo *r);
+void ndr_print_srvsvc_NetCharDevEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevEnum *r);
+void ndr_print_srvsvc_NetCharDevGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevGetInfo *r);
+void ndr_print_srvsvc_NetCharDevControl(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevControl *r);
+void ndr_print_srvsvc_NetCharDevQEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevQEnum *r);
+void ndr_print_srvsvc_NetCharDevQGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevQGetInfo *r);
+void ndr_print_srvsvc_NetCharDevQSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevQSetInfo *r);
+void ndr_print_srvsvc_NetCharDevQPurge(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevQPurge *r);
+void ndr_print_srvsvc_NetCharDevQPurgeSelf(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetCharDevQPurgeSelf *r);
+void ndr_print_srvsvc_NetConnEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetConnEnum *r);
+void ndr_print_srvsvc_NetFileEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetFileEnum *r);
+void ndr_print_srvsvc_NetFileGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetFileGetInfo *r);
+void ndr_print_srvsvc_NetFileClose(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetFileClose *r);
+void ndr_print_srvsvc_NetSessEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSessEnum *r);
+void ndr_print_srvsvc_NetSessDel(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSessDel *r);
+void ndr_print_srvsvc_NetShareAdd(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareAdd *r);
+void ndr_print_srvsvc_NetShareEnumAll(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareEnumAll *r);
+void ndr_print_srvsvc_NetShareGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareGetInfo *r);
+void ndr_print_srvsvc_NetShareSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareSetInfo *r);
+void ndr_print_srvsvc_NetShareDel(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareDel *r);
+void ndr_print_srvsvc_NetShareDelSticky(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareDelSticky *r);
+void ndr_print_srvsvc_NetShareCheck(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareCheck *r);
+void ndr_print_srvsvc_NetSrvGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSrvGetInfo *r);
+void ndr_print_srvsvc_NetSrvSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSrvSetInfo *r);
+void ndr_print_srvsvc_NetDiskEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetDiskEnum *r);
+void ndr_print_srvsvc_NetServerStatisticsGet(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetServerStatisticsGet *r);
+void ndr_print_srvsvc_NetTransportAdd(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetTransportAdd *r);
+void ndr_print_srvsvc_NetTransportEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetTransportEnum *r);
+void ndr_print_srvsvc_NetTransportDel(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetTransportDel *r);
+void ndr_print_srvsvc_NetRemoteTOD(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetRemoteTOD *r);
+void ndr_print_srvsvc_NetSetServiceBits(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSetServiceBits *r);
+void ndr_print_srvsvc_NetPathType(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetPathType *r);
+void ndr_print_srvsvc_NetPathCanonicalize(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetPathCanonicalize *r);
+void ndr_print_srvsvc_NetPathCompare(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetPathCompare *r);
+void ndr_print_srvsvc_NetNameValidate(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetNameValidate *r);
+void ndr_print_srvsvc_NETRPRNAMECANONICALIZE(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRPRNAMECANONICALIZE *r);
+void ndr_print_srvsvc_NetPRNameCompare(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetPRNameCompare *r);
+void ndr_print_srvsvc_NetShareEnum(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareEnum *r);
+void ndr_print_srvsvc_NetShareDelStart(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareDelStart *r);
+void ndr_print_srvsvc_NetShareDelCommit(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetShareDelCommit *r);
+void ndr_print_srvsvc_NetGetFileSecurity(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetGetFileSecurity *r);
+void ndr_print_srvsvc_NetSetFileSecurity(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetSetFileSecurity *r);
+void ndr_print_srvsvc_NetServerTransportAddEx(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetServerTransportAddEx *r);
+void ndr_print_srvsvc_NetServerSetServiceBitsEx(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NetServerSetServiceBitsEx *r);
+void ndr_print_srvsvc_NETRDFSGETVERSION(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSGETVERSION *r);
+void ndr_print_srvsvc_NETRDFSCREATELOCALPARTITION(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSCREATELOCALPARTITION *r);
+void ndr_print_srvsvc_NETRDFSDELETELOCALPARTITION(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSDELETELOCALPARTITION *r);
+void ndr_print_srvsvc_NETRDFSSETLOCALVOLUMESTATE(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSSETLOCALVOLUMESTATE *r);
+void ndr_print_srvsvc_NETRDFSSETSERVERINFO(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSSETSERVERINFO *r);
+void ndr_print_srvsvc_NETRDFSCREATEEXITPOINT(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSCREATEEXITPOINT *r);
+void ndr_print_srvsvc_NETRDFSDELETEEXITPOINT(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSDELETEEXITPOINT *r);
+void ndr_print_srvsvc_NETRDFSMODIFYPREFIX(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSMODIFYPREFIX *r);
+void ndr_print_srvsvc_NETRDFSFIXLOCALVOLUME(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSFIXLOCALVOLUME *r);
+void ndr_print_srvsvc_NETRDFSMANAGERREPORTSITEINFO(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRDFSMANAGERREPORTSITEINFO *r);
+void ndr_print_srvsvc_NETRSERVERTRANSPORTDELEX(struct ndr_print *ndr, const char *name, int flags, const struct srvsvc_NETRSERVERTRANSPORTDELEX *r);
+#endif /* _HEADER_NDR_srvsvc */
diff --git a/source/librpc/gen_ndr/ndr_wkssvc.c b/source/librpc/gen_ndr/ndr_wkssvc.c
new file mode 100644
index 00000000000..2af358727c3
--- /dev/null
+++ b/source/librpc/gen_ndr/ndr_wkssvc.c
@@ -0,0 +1,4787 @@
+/* parser auto-generated by pidl */
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_wkssvc.h"
+
+#include "librpc/gen_ndr/ndr_srvsvc.h"
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo100(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo100 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->platform_id));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->domain_name));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_major));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_minor));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->domain_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->domain_name, ndr_charset_length(r->domain_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo100(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo100 *r)
+{
+ uint32_t _ptr_server_name;
+ TALLOC_CTX *_mem_save_server_name_0;
+ uint32_t _ptr_domain_name;
+ TALLOC_CTX *_mem_save_domain_name_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->platform_id));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->server_name);
+ } else {
+ r->server_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_domain_name));
+ if (_ptr_domain_name) {
+ NDR_PULL_ALLOC(ndr, r->domain_name);
+ } else {
+ r->domain_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_major));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_minor));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+ if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ if (r->domain_name) {
+ _mem_save_domain_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->domain_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->domain_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->domain_name));
+ if (ndr_get_array_length(ndr, &r->domain_name) > ndr_get_array_size(ndr, &r->domain_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->domain_name), ndr_get_array_length(ndr, &r->domain_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->domain_name, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_domain_name_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo100(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo100 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo100");
+ ndr->depth++;
+ ndr_print_uint16(ndr, "platform_id", r->platform_id);
+ ndr_print_ptr(ndr, "server_name", r->server_name);
+ ndr->depth++;
+ if (r->server_name) {
+ ndr_print_string(ndr, "server_name", r->server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "domain_name", r->domain_name);
+ ndr->depth++;
+ if (r->domain_name) {
+ ndr_print_string(ndr, "domain_name", r->domain_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "version_major", r->version_major);
+ ndr_print_uint32(ndr, "version_minor", r->version_minor);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo101(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo101 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->platform_id));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->domain_name));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_major));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_minor));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->lan_root));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->domain_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->domain_name, ndr_charset_length(r->domain_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->lan_root) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->lan_root, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->lan_root, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->lan_root, ndr_charset_length(r->lan_root, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo101(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo101 *r)
+{
+ uint32_t _ptr_server_name;
+ TALLOC_CTX *_mem_save_server_name_0;
+ uint32_t _ptr_domain_name;
+ TALLOC_CTX *_mem_save_domain_name_0;
+ uint32_t _ptr_lan_root;
+ TALLOC_CTX *_mem_save_lan_root_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->platform_id));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->server_name);
+ } else {
+ r->server_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_domain_name));
+ if (_ptr_domain_name) {
+ NDR_PULL_ALLOC(ndr, r->domain_name);
+ } else {
+ r->domain_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_major));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_minor));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_lan_root));
+ if (_ptr_lan_root) {
+ NDR_PULL_ALLOC(ndr, r->lan_root);
+ } else {
+ r->lan_root = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+ if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ if (r->domain_name) {
+ _mem_save_domain_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->domain_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->domain_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->domain_name));
+ if (ndr_get_array_length(ndr, &r->domain_name) > ndr_get_array_size(ndr, &r->domain_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->domain_name), ndr_get_array_length(ndr, &r->domain_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->domain_name, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_domain_name_0, 0);
+ }
+ if (r->lan_root) {
+ _mem_save_lan_root_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->lan_root, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->lan_root));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->lan_root));
+ if (ndr_get_array_length(ndr, &r->lan_root) > ndr_get_array_size(ndr, &r->lan_root)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->lan_root), ndr_get_array_length(ndr, &r->lan_root));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->lan_root), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->lan_root, ndr_get_array_length(ndr, &r->lan_root), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_lan_root_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo101(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo101 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo101");
+ ndr->depth++;
+ ndr_print_uint16(ndr, "platform_id", r->platform_id);
+ ndr_print_ptr(ndr, "server_name", r->server_name);
+ ndr->depth++;
+ if (r->server_name) {
+ ndr_print_string(ndr, "server_name", r->server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "domain_name", r->domain_name);
+ ndr->depth++;
+ if (r->domain_name) {
+ ndr_print_string(ndr, "domain_name", r->domain_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "version_major", r->version_major);
+ ndr_print_uint32(ndr, "version_minor", r->version_minor);
+ ndr_print_ptr(ndr, "lan_root", r->lan_root);
+ ndr->depth++;
+ if (r->lan_root) {
+ ndr_print_string(ndr, "lan_root", r->lan_root);
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo102(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo102 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->platform_id));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->domain_name));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_major));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->version_minor));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->lan_root));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->logged_on_users));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->domain_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->domain_name, ndr_charset_length(r->domain_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->lan_root) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->lan_root, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->lan_root, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->lan_root, ndr_charset_length(r->lan_root, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo102(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo102 *r)
+{
+ uint32_t _ptr_server_name;
+ TALLOC_CTX *_mem_save_server_name_0;
+ uint32_t _ptr_domain_name;
+ TALLOC_CTX *_mem_save_domain_name_0;
+ uint32_t _ptr_lan_root;
+ TALLOC_CTX *_mem_save_lan_root_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->platform_id));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->server_name);
+ } else {
+ r->server_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_domain_name));
+ if (_ptr_domain_name) {
+ NDR_PULL_ALLOC(ndr, r->domain_name);
+ } else {
+ r->domain_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_major));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version_minor));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_lan_root));
+ if (_ptr_lan_root) {
+ NDR_PULL_ALLOC(ndr, r->lan_root);
+ } else {
+ r->lan_root = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->logged_on_users));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+ if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ if (r->domain_name) {
+ _mem_save_domain_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->domain_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->domain_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->domain_name));
+ if (ndr_get_array_length(ndr, &r->domain_name) > ndr_get_array_size(ndr, &r->domain_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->domain_name), ndr_get_array_length(ndr, &r->domain_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->domain_name, ndr_get_array_length(ndr, &r->domain_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_domain_name_0, 0);
+ }
+ if (r->lan_root) {
+ _mem_save_lan_root_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->lan_root, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->lan_root));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->lan_root));
+ if (ndr_get_array_length(ndr, &r->lan_root) > ndr_get_array_size(ndr, &r->lan_root)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->lan_root), ndr_get_array_length(ndr, &r->lan_root));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->lan_root), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->lan_root, ndr_get_array_length(ndr, &r->lan_root), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_lan_root_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo102(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo102 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo102");
+ ndr->depth++;
+ ndr_print_uint16(ndr, "platform_id", r->platform_id);
+ ndr_print_ptr(ndr, "server_name", r->server_name);
+ ndr->depth++;
+ if (r->server_name) {
+ ndr_print_string(ndr, "server_name", r->server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "domain_name", r->domain_name);
+ ndr->depth++;
+ if (r->domain_name) {
+ ndr_print_string(ndr, "domain_name", r->domain_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "version_major", r->version_major);
+ ndr_print_uint32(ndr, "version_minor", r->version_minor);
+ ndr_print_ptr(ndr, "lan_root", r->lan_root);
+ ndr->depth++;
+ if (r->lan_root) {
+ ndr_print_string(ndr, "lan_root", r->lan_root);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "logged_on_users", r->logged_on_users);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo502(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo502 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->char_wait));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->collection_time));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->maximum_collection_count));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->keep_connection));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_commands));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->session_timeout));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size_char_buf));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_threads));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->lock_quota));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->lock_increment));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->lock_maximum));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pipe_increment));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pipe_maximum));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->cache_file_timeout));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->dormant_file_limit));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->read_ahead_throughput));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_mailslot_buffers));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_srv_announce_buffers));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_illegal_dgram_events));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->dgram_event_reset_freq));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->log_election_packets));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_opportunistic_locking));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_unlock_behind));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_close_behind));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->buf_named_pipes));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_lock_read_unlock));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->utilize_nt_caching));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_raw_read));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_raw_write));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_write_raw_data));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_encryption));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->buf_files_deny_write));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->buf_read_only_files));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->force_core_create_mode));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->use_512_byte_max_transfer));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo502(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo502 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->char_wait));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->collection_time));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->maximum_collection_count));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->keep_connection));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_commands));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->session_timeout));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size_char_buf));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_threads));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->lock_quota));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->lock_increment));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->lock_maximum));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pipe_increment));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pipe_maximum));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cache_file_timeout));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->dormant_file_limit));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->read_ahead_throughput));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_mailslot_buffers));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_srv_announce_buffers));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_illegal_dgram_events));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->dgram_event_reset_freq));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->log_election_packets));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_opportunistic_locking));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_unlock_behind));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_close_behind));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->buf_named_pipes));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_lock_read_unlock));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->utilize_nt_caching));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_raw_read));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_raw_write));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_write_raw_data));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_encryption));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->buf_files_deny_write));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->buf_read_only_files));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->force_core_create_mode));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->use_512_byte_max_transfer));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo502(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo502 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo502");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "char_wait", r->char_wait);
+ ndr_print_uint32(ndr, "collection_time", r->collection_time);
+ ndr_print_uint32(ndr, "maximum_collection_count", r->maximum_collection_count);
+ ndr_print_uint32(ndr, "keep_connection", r->keep_connection);
+ ndr_print_uint32(ndr, "max_commands", r->max_commands);
+ ndr_print_uint32(ndr, "session_timeout", r->session_timeout);
+ ndr_print_uint32(ndr, "size_char_buf", r->size_char_buf);
+ ndr_print_uint32(ndr, "max_threads", r->max_threads);
+ ndr_print_uint32(ndr, "lock_quota", r->lock_quota);
+ ndr_print_uint32(ndr, "lock_increment", r->lock_increment);
+ ndr_print_uint32(ndr, "lock_maximum", r->lock_maximum);
+ ndr_print_uint32(ndr, "pipe_increment", r->pipe_increment);
+ ndr_print_uint32(ndr, "pipe_maximum", r->pipe_maximum);
+ ndr_print_uint32(ndr, "cache_file_timeout", r->cache_file_timeout);
+ ndr_print_uint32(ndr, "dormant_file_limit", r->dormant_file_limit);
+ ndr_print_uint32(ndr, "read_ahead_throughput", r->read_ahead_throughput);
+ ndr_print_uint32(ndr, "num_mailslot_buffers", r->num_mailslot_buffers);
+ ndr_print_uint32(ndr, "num_srv_announce_buffers", r->num_srv_announce_buffers);
+ ndr_print_uint32(ndr, "max_illegal_dgram_events", r->max_illegal_dgram_events);
+ ndr_print_uint32(ndr, "dgram_event_reset_freq", r->dgram_event_reset_freq);
+ ndr_print_uint32(ndr, "log_election_packets", r->log_election_packets);
+ ndr_print_uint32(ndr, "use_opportunistic_locking", r->use_opportunistic_locking);
+ ndr_print_uint32(ndr, "use_unlock_behind", r->use_unlock_behind);
+ ndr_print_uint32(ndr, "use_close_behind", r->use_close_behind);
+ ndr_print_uint32(ndr, "buf_named_pipes", r->buf_named_pipes);
+ ndr_print_uint32(ndr, "use_lock_read_unlock", r->use_lock_read_unlock);
+ ndr_print_uint32(ndr, "utilize_nt_caching", r->utilize_nt_caching);
+ ndr_print_uint32(ndr, "use_raw_read", r->use_raw_read);
+ ndr_print_uint32(ndr, "use_raw_write", r->use_raw_write);
+ ndr_print_uint32(ndr, "use_write_raw_data", r->use_write_raw_data);
+ ndr_print_uint32(ndr, "use_encryption", r->use_encryption);
+ ndr_print_uint32(ndr, "buf_files_deny_write", r->buf_files_deny_write);
+ ndr_print_uint32(ndr, "buf_read_only_files", r->buf_read_only_files);
+ ndr_print_uint32(ndr, "force_core_create_mode", r->force_core_create_mode);
+ ndr_print_uint32(ndr, "use_512_byte_max_transfer", r->use_512_byte_max_transfer);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1010(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1010 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->char_wait));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1010(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1010 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->char_wait));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1010(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1010 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1010");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "char_wait", r->char_wait);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1011(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1011 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->collection_time));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1011(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1011 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->collection_time));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1011(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1011 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1011");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "collection_time", r->collection_time);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1012(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1012 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->maximum_collection_count));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1012(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1012 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->maximum_collection_count));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1012(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1012 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1012");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "maximum_collection_count", r->maximum_collection_count);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1013(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1013 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->keep_connection));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1013(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1013 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->keep_connection));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1013(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1013 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1013");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "keep_connection", r->keep_connection);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1018(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1018 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->session_timeout));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1018(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1018 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->session_timeout));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1018(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1018 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1018");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "session_timeout", r->session_timeout);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1023(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1023 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size_char_buf));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1023(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1023 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size_char_buf));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1023(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1023 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1023");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "size_char_buf", r->size_char_buf);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1027(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1027 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->errorlog_sz));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1027(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1027 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->errorlog_sz));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1027(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1027 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1027");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "errorlog_sz", r->errorlog_sz);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo1033(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaInfo1033 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->max_threads));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo1033(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaInfo1033 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->max_threads));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo1033(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1033 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaInfo1033");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "max_threads", r->max_threads);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaInfo(struct ndr_push *ndr, int ndr_flags, const union wkssvc_NetWkstaInfo *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, level));
+ switch (level) {
+ case 100:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info100));
+ break;
+
+ case 101:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info101));
+ break;
+
+ case 102:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info102));
+ break;
+
+ case 502:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info502));
+ break;
+
+ case 1010:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1010));
+ break;
+
+ case 1011:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1011));
+ break;
+
+ case 1012:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1012));
+ break;
+
+ case 1013:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1013));
+ break;
+
+ case 1018:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1018));
+ break;
+
+ case 1023:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1023));
+ break;
+
+ case 1027:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1027));
+ break;
+
+ case 1033:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1033));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 100:
+ if (r->info100) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo100(ndr, NDR_SCALARS|NDR_BUFFERS, r->info100));
+ }
+ break;
+
+ case 101:
+ if (r->info101) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo101(ndr, NDR_SCALARS|NDR_BUFFERS, r->info101));
+ }
+ break;
+
+ case 102:
+ if (r->info102) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo102(ndr, NDR_SCALARS|NDR_BUFFERS, r->info102));
+ }
+ break;
+
+ case 502:
+ if (r->info502) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo502(ndr, NDR_SCALARS, r->info502));
+ }
+ break;
+
+ case 1010:
+ if (r->info1010) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1010(ndr, NDR_SCALARS, r->info1010));
+ }
+ break;
+
+ case 1011:
+ if (r->info1011) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1011(ndr, NDR_SCALARS, r->info1011));
+ }
+ break;
+
+ case 1012:
+ if (r->info1012) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1012(ndr, NDR_SCALARS, r->info1012));
+ }
+ break;
+
+ case 1013:
+ if (r->info1013) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1013(ndr, NDR_SCALARS, r->info1013));
+ }
+ break;
+
+ case 1018:
+ if (r->info1018) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1018(ndr, NDR_SCALARS, r->info1018));
+ }
+ break;
+
+ case 1023:
+ if (r->info1023) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1023(ndr, NDR_SCALARS, r->info1023));
+ }
+ break;
+
+ case 1027:
+ if (r->info1027) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1027(ndr, NDR_SCALARS, r->info1027));
+ }
+ break;
+
+ case 1033:
+ if (r->info1033) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo1033(ndr, NDR_SCALARS, r->info1033));
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaInfo(struct ndr_pull *ndr, int ndr_flags, union wkssvc_NetWkstaInfo *r)
+{
+ int level;
+ uint32_t _level;
+ TALLOC_CTX *_mem_save_info100_0;
+ TALLOC_CTX *_mem_save_info101_0;
+ TALLOC_CTX *_mem_save_info102_0;
+ TALLOC_CTX *_mem_save_info502_0;
+ TALLOC_CTX *_mem_save_info1010_0;
+ TALLOC_CTX *_mem_save_info1011_0;
+ TALLOC_CTX *_mem_save_info1012_0;
+ TALLOC_CTX *_mem_save_info1013_0;
+ TALLOC_CTX *_mem_save_info1018_0;
+ TALLOC_CTX *_mem_save_info1023_0;
+ TALLOC_CTX *_mem_save_info1027_0;
+ TALLOC_CTX *_mem_save_info1033_0;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
+ if (_level != level) {
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u for wkssvc_NetWkstaInfo", _level);
+ }
+ switch (level) {
+ case 100: {
+ uint32_t _ptr_info100;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info100));
+ if (_ptr_info100) {
+ NDR_PULL_ALLOC(ndr, r->info100);
+ } else {
+ r->info100 = NULL;
+ }
+ break; }
+
+ case 101: {
+ uint32_t _ptr_info101;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info101));
+ if (_ptr_info101) {
+ NDR_PULL_ALLOC(ndr, r->info101);
+ } else {
+ r->info101 = NULL;
+ }
+ break; }
+
+ case 102: {
+ uint32_t _ptr_info102;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info102));
+ if (_ptr_info102) {
+ NDR_PULL_ALLOC(ndr, r->info102);
+ } else {
+ r->info102 = NULL;
+ }
+ break; }
+
+ case 502: {
+ uint32_t _ptr_info502;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info502));
+ if (_ptr_info502) {
+ NDR_PULL_ALLOC(ndr, r->info502);
+ } else {
+ r->info502 = NULL;
+ }
+ break; }
+
+ case 1010: {
+ uint32_t _ptr_info1010;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1010));
+ if (_ptr_info1010) {
+ NDR_PULL_ALLOC(ndr, r->info1010);
+ } else {
+ r->info1010 = NULL;
+ }
+ break; }
+
+ case 1011: {
+ uint32_t _ptr_info1011;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1011));
+ if (_ptr_info1011) {
+ NDR_PULL_ALLOC(ndr, r->info1011);
+ } else {
+ r->info1011 = NULL;
+ }
+ break; }
+
+ case 1012: {
+ uint32_t _ptr_info1012;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1012));
+ if (_ptr_info1012) {
+ NDR_PULL_ALLOC(ndr, r->info1012);
+ } else {
+ r->info1012 = NULL;
+ }
+ break; }
+
+ case 1013: {
+ uint32_t _ptr_info1013;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1013));
+ if (_ptr_info1013) {
+ NDR_PULL_ALLOC(ndr, r->info1013);
+ } else {
+ r->info1013 = NULL;
+ }
+ break; }
+
+ case 1018: {
+ uint32_t _ptr_info1018;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1018));
+ if (_ptr_info1018) {
+ NDR_PULL_ALLOC(ndr, r->info1018);
+ } else {
+ r->info1018 = NULL;
+ }
+ break; }
+
+ case 1023: {
+ uint32_t _ptr_info1023;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1023));
+ if (_ptr_info1023) {
+ NDR_PULL_ALLOC(ndr, r->info1023);
+ } else {
+ r->info1023 = NULL;
+ }
+ break; }
+
+ case 1027: {
+ uint32_t _ptr_info1027;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1027));
+ if (_ptr_info1027) {
+ NDR_PULL_ALLOC(ndr, r->info1027);
+ } else {
+ r->info1027 = NULL;
+ }
+ break; }
+
+ case 1033: {
+ uint32_t _ptr_info1033;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1033));
+ if (_ptr_info1033) {
+ NDR_PULL_ALLOC(ndr, r->info1033);
+ } else {
+ r->info1033 = NULL;
+ }
+ break; }
+
+ default: {
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 100:
+ if (r->info100) {
+ _mem_save_info100_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info100, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo100(ndr, NDR_SCALARS|NDR_BUFFERS, r->info100));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info100_0, 0);
+ }
+ break;
+
+ case 101:
+ if (r->info101) {
+ _mem_save_info101_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info101, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo101(ndr, NDR_SCALARS|NDR_BUFFERS, r->info101));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info101_0, 0);
+ }
+ break;
+
+ case 102:
+ if (r->info102) {
+ _mem_save_info102_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info102, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo102(ndr, NDR_SCALARS|NDR_BUFFERS, r->info102));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info102_0, 0);
+ }
+ break;
+
+ case 502:
+ if (r->info502) {
+ _mem_save_info502_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info502, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo502(ndr, NDR_SCALARS, r->info502));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info502_0, 0);
+ }
+ break;
+
+ case 1010:
+ if (r->info1010) {
+ _mem_save_info1010_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1010, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1010(ndr, NDR_SCALARS, r->info1010));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1010_0, 0);
+ }
+ break;
+
+ case 1011:
+ if (r->info1011) {
+ _mem_save_info1011_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1011, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1011(ndr, NDR_SCALARS, r->info1011));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1011_0, 0);
+ }
+ break;
+
+ case 1012:
+ if (r->info1012) {
+ _mem_save_info1012_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1012, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1012(ndr, NDR_SCALARS, r->info1012));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1012_0, 0);
+ }
+ break;
+
+ case 1013:
+ if (r->info1013) {
+ _mem_save_info1013_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1013, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1013(ndr, NDR_SCALARS, r->info1013));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1013_0, 0);
+ }
+ break;
+
+ case 1018:
+ if (r->info1018) {
+ _mem_save_info1018_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1018, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1018(ndr, NDR_SCALARS, r->info1018));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1018_0, 0);
+ }
+ break;
+
+ case 1023:
+ if (r->info1023) {
+ _mem_save_info1023_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1023, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1023(ndr, NDR_SCALARS, r->info1023));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1023_0, 0);
+ }
+ break;
+
+ case 1027:
+ if (r->info1027) {
+ _mem_save_info1027_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1027, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1027(ndr, NDR_SCALARS, r->info1027));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1027_0, 0);
+ }
+ break;
+
+ case 1033:
+ if (r->info1033) {
+ _mem_save_info1033_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info1033, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo1033(ndr, NDR_SCALARS, r->info1033));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1033_0, 0);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaInfo(struct ndr_print *ndr, const char *name, const union wkssvc_NetWkstaInfo *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "wkssvc_NetWkstaInfo");
+ switch (level) {
+ case 100:
+ ndr_print_ptr(ndr, "info100", r->info100);
+ ndr->depth++;
+ if (r->info100) {
+ ndr_print_wkssvc_NetWkstaInfo100(ndr, "info100", r->info100);
+ }
+ ndr->depth--;
+ break;
+
+ case 101:
+ ndr_print_ptr(ndr, "info101", r->info101);
+ ndr->depth++;
+ if (r->info101) {
+ ndr_print_wkssvc_NetWkstaInfo101(ndr, "info101", r->info101);
+ }
+ ndr->depth--;
+ break;
+
+ case 102:
+ ndr_print_ptr(ndr, "info102", r->info102);
+ ndr->depth++;
+ if (r->info102) {
+ ndr_print_wkssvc_NetWkstaInfo102(ndr, "info102", r->info102);
+ }
+ ndr->depth--;
+ break;
+
+ case 502:
+ ndr_print_ptr(ndr, "info502", r->info502);
+ ndr->depth++;
+ if (r->info502) {
+ ndr_print_wkssvc_NetWkstaInfo502(ndr, "info502", r->info502);
+ }
+ ndr->depth--;
+ break;
+
+ case 1010:
+ ndr_print_ptr(ndr, "info1010", r->info1010);
+ ndr->depth++;
+ if (r->info1010) {
+ ndr_print_wkssvc_NetWkstaInfo1010(ndr, "info1010", r->info1010);
+ }
+ ndr->depth--;
+ break;
+
+ case 1011:
+ ndr_print_ptr(ndr, "info1011", r->info1011);
+ ndr->depth++;
+ if (r->info1011) {
+ ndr_print_wkssvc_NetWkstaInfo1011(ndr, "info1011", r->info1011);
+ }
+ ndr->depth--;
+ break;
+
+ case 1012:
+ ndr_print_ptr(ndr, "info1012", r->info1012);
+ ndr->depth++;
+ if (r->info1012) {
+ ndr_print_wkssvc_NetWkstaInfo1012(ndr, "info1012", r->info1012);
+ }
+ ndr->depth--;
+ break;
+
+ case 1013:
+ ndr_print_ptr(ndr, "info1013", r->info1013);
+ ndr->depth++;
+ if (r->info1013) {
+ ndr_print_wkssvc_NetWkstaInfo1013(ndr, "info1013", r->info1013);
+ }
+ ndr->depth--;
+ break;
+
+ case 1018:
+ ndr_print_ptr(ndr, "info1018", r->info1018);
+ ndr->depth++;
+ if (r->info1018) {
+ ndr_print_wkssvc_NetWkstaInfo1018(ndr, "info1018", r->info1018);
+ }
+ ndr->depth--;
+ break;
+
+ case 1023:
+ ndr_print_ptr(ndr, "info1023", r->info1023);
+ ndr->depth++;
+ if (r->info1023) {
+ ndr_print_wkssvc_NetWkstaInfo1023(ndr, "info1023", r->info1023);
+ }
+ ndr->depth--;
+ break;
+
+ case 1027:
+ ndr_print_ptr(ndr, "info1027", r->info1027);
+ ndr->depth++;
+ if (r->info1027) {
+ ndr_print_wkssvc_NetWkstaInfo1027(ndr, "info1027", r->info1027);
+ }
+ ndr->depth--;
+ break;
+
+ case 1033:
+ ndr_print_ptr(ndr, "info1033", r->info1033);
+ ndr->depth++;
+ if (r->info1033) {
+ ndr_print_wkssvc_NetWkstaInfo1033(ndr, "info1033", r->info1033);
+ }
+ ndr->depth--;
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+NTSTATUS ndr_push_USER_INFO_0(struct ndr_push *ndr, int ndr_flags, const struct USER_INFO_0 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->user, ndr_charset_length(r->user, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_USER_INFO_0(struct ndr_pull *ndr, int ndr_flags, struct USER_INFO_0 *r)
+{
+ uint32_t _ptr_user;
+ TALLOC_CTX *_mem_save_user_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user));
+ if (_ptr_user) {
+ NDR_PULL_ALLOC(ndr, r->user);
+ } else {
+ r->user = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user) {
+ _mem_save_user_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->user));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->user));
+ if (ndr_get_array_length(ndr, &r->user) > ndr_get_array_size(ndr, &r->user)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->user), ndr_get_array_length(ndr, &r->user));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->user), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->user, ndr_get_array_length(ndr, &r->user), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_USER_INFO_0(struct ndr_print *ndr, const char *name, const struct USER_INFO_0 *r)
+{
+ ndr_print_struct(ndr, name, "USER_INFO_0");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "user", r->user);
+ ndr->depth++;
+ if (r->user) {
+ ndr_print_string(ndr, "user", r->user);
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_USER_INFO_0_CONTAINER(struct ndr_push *ndr, int ndr_flags, const struct USER_INFO_0_CONTAINER *r)
+{
+ uint32_t cntr_user0_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->entries_read));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user0));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user0) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->entries_read));
+ for (cntr_user0_1 = 0; cntr_user0_1 < r->entries_read; cntr_user0_1++) {
+ NDR_CHECK(ndr_push_USER_INFO_0(ndr, NDR_SCALARS, &r->user0[cntr_user0_1]));
+ }
+ for (cntr_user0_1 = 0; cntr_user0_1 < r->entries_read; cntr_user0_1++) {
+ NDR_CHECK(ndr_push_USER_INFO_0(ndr, NDR_BUFFERS, &r->user0[cntr_user0_1]));
+ }
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_USER_INFO_0_CONTAINER(struct ndr_pull *ndr, int ndr_flags, struct USER_INFO_0_CONTAINER *r)
+{
+ uint32_t _ptr_user0;
+ uint32_t cntr_user0_1;
+ TALLOC_CTX *_mem_save_user0_0;
+ TALLOC_CTX *_mem_save_user0_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->entries_read));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user0));
+ if (_ptr_user0) {
+ NDR_PULL_ALLOC(ndr, r->user0);
+ } else {
+ r->user0 = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user0) {
+ _mem_save_user0_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user0, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->user0));
+ NDR_PULL_ALLOC_N(ndr, r->user0, ndr_get_array_size(ndr, &r->user0));
+ _mem_save_user0_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user0, 0);
+ for (cntr_user0_1 = 0; cntr_user0_1 < r->entries_read; cntr_user0_1++) {
+ NDR_CHECK(ndr_pull_USER_INFO_0(ndr, NDR_SCALARS, &r->user0[cntr_user0_1]));
+ }
+ for (cntr_user0_1 = 0; cntr_user0_1 < r->entries_read; cntr_user0_1++) {
+ NDR_CHECK(ndr_pull_USER_INFO_0(ndr, NDR_BUFFERS, &r->user0[cntr_user0_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user0_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user0_0, 0);
+ }
+ if (r->user0) {
+ NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->user0, r->entries_read));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_USER_INFO_0_CONTAINER(struct ndr_print *ndr, const char *name, const struct USER_INFO_0_CONTAINER *r)
+{
+ uint32_t cntr_user0_1;
+ ndr_print_struct(ndr, name, "USER_INFO_0_CONTAINER");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "entries_read", r->entries_read);
+ ndr_print_ptr(ndr, "user0", r->user0);
+ ndr->depth++;
+ if (r->user0) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "user0", r->entries_read);
+ ndr->depth++;
+ for (cntr_user0_1=0;cntr_user0_1<r->entries_read;cntr_user0_1++) {
+ char *idx_1=NULL;
+ asprintf(&idx_1, "[%d]", cntr_user0_1);
+ if (idx_1) {
+ ndr_print_USER_INFO_0(ndr, "user0", &r->user0[cntr_user0_1]);
+ free(idx_1);
+ }
+ }
+ ndr->depth--;
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_USER_INFO_1(struct ndr_push *ndr, int ndr_flags, const struct USER_INFO_1 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user_name));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->logon_domain));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->other_domains));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->logon_server));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->user_name, ndr_charset_length(r->user_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->logon_domain) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->logon_domain, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->logon_domain, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->logon_domain, ndr_charset_length(r->logon_domain, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->other_domains) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->other_domains, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->other_domains, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->other_domains, ndr_charset_length(r->other_domains, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->logon_server) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->logon_server, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->logon_server, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->logon_server, ndr_charset_length(r->logon_server, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_USER_INFO_1(struct ndr_pull *ndr, int ndr_flags, struct USER_INFO_1 *r)
+{
+ uint32_t _ptr_user_name;
+ TALLOC_CTX *_mem_save_user_name_0;
+ uint32_t _ptr_logon_domain;
+ TALLOC_CTX *_mem_save_logon_domain_0;
+ uint32_t _ptr_other_domains;
+ TALLOC_CTX *_mem_save_other_domains_0;
+ uint32_t _ptr_logon_server;
+ TALLOC_CTX *_mem_save_logon_server_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+ if (_ptr_user_name) {
+ NDR_PULL_ALLOC(ndr, r->user_name);
+ } else {
+ r->user_name = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_logon_domain));
+ if (_ptr_logon_domain) {
+ NDR_PULL_ALLOC(ndr, r->logon_domain);
+ } else {
+ r->logon_domain = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_other_domains));
+ if (_ptr_other_domains) {
+ NDR_PULL_ALLOC(ndr, r->other_domains);
+ } else {
+ r->other_domains = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_logon_server));
+ if (_ptr_logon_server) {
+ NDR_PULL_ALLOC(ndr, r->logon_server);
+ } else {
+ r->logon_server = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user_name) {
+ _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->user_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->user_name));
+ if (ndr_get_array_length(ndr, &r->user_name) > ndr_get_array_size(ndr, &r->user_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->user_name), ndr_get_array_length(ndr, &r->user_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->user_name, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+ }
+ if (r->logon_domain) {
+ _mem_save_logon_domain_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->logon_domain, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->logon_domain));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->logon_domain));
+ if (ndr_get_array_length(ndr, &r->logon_domain) > ndr_get_array_size(ndr, &r->logon_domain)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->logon_domain), ndr_get_array_length(ndr, &r->logon_domain));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->logon_domain), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->logon_domain, ndr_get_array_length(ndr, &r->logon_domain), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_logon_domain_0, 0);
+ }
+ if (r->other_domains) {
+ _mem_save_other_domains_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->other_domains, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->other_domains));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->other_domains));
+ if (ndr_get_array_length(ndr, &r->other_domains) > ndr_get_array_size(ndr, &r->other_domains)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->other_domains), ndr_get_array_length(ndr, &r->other_domains));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->other_domains), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->other_domains, ndr_get_array_length(ndr, &r->other_domains), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_other_domains_0, 0);
+ }
+ if (r->logon_server) {
+ _mem_save_logon_server_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->logon_server, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->logon_server));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->logon_server));
+ if (ndr_get_array_length(ndr, &r->logon_server) > ndr_get_array_size(ndr, &r->logon_server)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->logon_server), ndr_get_array_length(ndr, &r->logon_server));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->logon_server), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->logon_server, ndr_get_array_length(ndr, &r->logon_server), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_logon_server_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_USER_INFO_1(struct ndr_print *ndr, const char *name, const struct USER_INFO_1 *r)
+{
+ ndr_print_struct(ndr, name, "USER_INFO_1");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "user_name", r->user_name);
+ ndr->depth++;
+ if (r->user_name) {
+ ndr_print_string(ndr, "user_name", r->user_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "logon_domain", r->logon_domain);
+ ndr->depth++;
+ if (r->logon_domain) {
+ ndr_print_string(ndr, "logon_domain", r->logon_domain);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "other_domains", r->other_domains);
+ ndr->depth++;
+ if (r->other_domains) {
+ ndr_print_string(ndr, "other_domains", r->other_domains);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "logon_server", r->logon_server);
+ ndr->depth++;
+ if (r->logon_server) {
+ ndr_print_string(ndr, "logon_server", r->logon_server);
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_USER_INFO_1_CONTAINER(struct ndr_push *ndr, int ndr_flags, const struct USER_INFO_1_CONTAINER *r)
+{
+ uint32_t cntr_user1_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->entries_read));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user1));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user1) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->entries_read));
+ for (cntr_user1_1 = 0; cntr_user1_1 < r->entries_read; cntr_user1_1++) {
+ NDR_CHECK(ndr_push_USER_INFO_1(ndr, NDR_SCALARS, &r->user1[cntr_user1_1]));
+ }
+ for (cntr_user1_1 = 0; cntr_user1_1 < r->entries_read; cntr_user1_1++) {
+ NDR_CHECK(ndr_push_USER_INFO_1(ndr, NDR_BUFFERS, &r->user1[cntr_user1_1]));
+ }
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_USER_INFO_1_CONTAINER(struct ndr_pull *ndr, int ndr_flags, struct USER_INFO_1_CONTAINER *r)
+{
+ uint32_t _ptr_user1;
+ uint32_t cntr_user1_1;
+ TALLOC_CTX *_mem_save_user1_0;
+ TALLOC_CTX *_mem_save_user1_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->entries_read));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user1));
+ if (_ptr_user1) {
+ NDR_PULL_ALLOC(ndr, r->user1);
+ } else {
+ r->user1 = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->user1) {
+ _mem_save_user1_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user1, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->user1));
+ NDR_PULL_ALLOC_N(ndr, r->user1, ndr_get_array_size(ndr, &r->user1));
+ _mem_save_user1_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user1, 0);
+ for (cntr_user1_1 = 0; cntr_user1_1 < r->entries_read; cntr_user1_1++) {
+ NDR_CHECK(ndr_pull_USER_INFO_1(ndr, NDR_SCALARS, &r->user1[cntr_user1_1]));
+ }
+ for (cntr_user1_1 = 0; cntr_user1_1 < r->entries_read; cntr_user1_1++) {
+ NDR_CHECK(ndr_pull_USER_INFO_1(ndr, NDR_BUFFERS, &r->user1[cntr_user1_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user1_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user1_0, 0);
+ }
+ if (r->user1) {
+ NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->user1, r->entries_read));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_USER_INFO_1_CONTAINER(struct ndr_print *ndr, const char *name, const struct USER_INFO_1_CONTAINER *r)
+{
+ uint32_t cntr_user1_1;
+ ndr_print_struct(ndr, name, "USER_INFO_1_CONTAINER");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "entries_read", r->entries_read);
+ ndr_print_ptr(ndr, "user1", r->user1);
+ ndr->depth++;
+ if (r->user1) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "user1", r->entries_read);
+ ndr->depth++;
+ for (cntr_user1_1=0;cntr_user1_1<r->entries_read;cntr_user1_1++) {
+ char *idx_1=NULL;
+ asprintf(&idx_1, "[%d]", cntr_user1_1);
+ if (idx_1) {
+ ndr_print_USER_INFO_1(ndr, "user1", &r->user1[cntr_user1_1]);
+ free(idx_1);
+ }
+ }
+ ndr->depth--;
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKS_USER_ENUM_UNION(struct ndr_push *ndr, int ndr_flags, const union WKS_USER_ENUM_UNION *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, level));
+ switch (level) {
+ case 0:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user0));
+ break;
+
+ case 1:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->user1));
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 0:
+ if (r->user0) {
+ NDR_CHECK(ndr_push_USER_INFO_0_CONTAINER(ndr, NDR_SCALARS|NDR_BUFFERS, r->user0));
+ }
+ break;
+
+ case 1:
+ if (r->user1) {
+ NDR_CHECK(ndr_push_USER_INFO_1_CONTAINER(ndr, NDR_SCALARS|NDR_BUFFERS, r->user1));
+ }
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKS_USER_ENUM_UNION(struct ndr_pull *ndr, int ndr_flags, union WKS_USER_ENUM_UNION *r)
+{
+ int level;
+ uint32_t _level;
+ TALLOC_CTX *_mem_save_user0_0;
+ TALLOC_CTX *_mem_save_user1_0;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
+ if (_level != level) {
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u for WKS_USER_ENUM_UNION", _level);
+ }
+ switch (level) {
+ case 0: {
+ uint32_t _ptr_user0;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user0));
+ if (_ptr_user0) {
+ NDR_PULL_ALLOC(ndr, r->user0);
+ } else {
+ r->user0 = NULL;
+ }
+ break; }
+
+ case 1: {
+ uint32_t _ptr_user1;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user1));
+ if (_ptr_user1) {
+ NDR_PULL_ALLOC(ndr, r->user1);
+ } else {
+ r->user1 = NULL;
+ }
+ break; }
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 0:
+ if (r->user0) {
+ _mem_save_user0_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user0, 0);
+ NDR_CHECK(ndr_pull_USER_INFO_0_CONTAINER(ndr, NDR_SCALARS|NDR_BUFFERS, r->user0));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user0_0, 0);
+ }
+ break;
+
+ case 1:
+ if (r->user1) {
+ _mem_save_user1_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->user1, 0);
+ NDR_CHECK(ndr_pull_USER_INFO_1_CONTAINER(ndr, NDR_SCALARS|NDR_BUFFERS, r->user1));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user1_0, 0);
+ }
+ break;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKS_USER_ENUM_UNION(struct ndr_print *ndr, const char *name, const union WKS_USER_ENUM_UNION *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "WKS_USER_ENUM_UNION");
+ switch (level) {
+ case 0:
+ ndr_print_ptr(ndr, "user0", r->user0);
+ ndr->depth++;
+ if (r->user0) {
+ ndr_print_USER_INFO_0_CONTAINER(ndr, "user0", r->user0);
+ }
+ ndr->depth--;
+ break;
+
+ case 1:
+ ndr_print_ptr(ndr, "user1", r->user1);
+ ndr->depth++;
+ if (r->user1) {
+ ndr_print_USER_INFO_1_CONTAINER(ndr, "user1", r->user1);
+ }
+ ndr->depth--;
+ break;
+
+ default:
+ ndr_print_bad_level(ndr, name, level);
+ }
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaTransportInfo0(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaTransportInfo0 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->quality_of_service));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->vc_count));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->name));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->address));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->wan_link));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->name, ndr_charset_length(r->name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->address) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->address, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->address, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->address, ndr_charset_length(r->address, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaTransportInfo0(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaTransportInfo0 *r)
+{
+ uint32_t _ptr_name;
+ TALLOC_CTX *_mem_save_name_0;
+ uint32_t _ptr_address;
+ TALLOC_CTX *_mem_save_address_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->quality_of_service));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->vc_count));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_name));
+ if (_ptr_name) {
+ NDR_PULL_ALLOC(ndr, r->name);
+ } else {
+ r->name = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_address));
+ if (_ptr_address) {
+ NDR_PULL_ALLOC(ndr, r->address);
+ } else {
+ r->address = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->wan_link));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->name) {
+ _mem_save_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->name));
+ if (ndr_get_array_length(ndr, &r->name) > ndr_get_array_size(ndr, &r->name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->name), ndr_get_array_length(ndr, &r->name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->name, ndr_get_array_length(ndr, &r->name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_name_0, 0);
+ }
+ if (r->address) {
+ _mem_save_address_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->address, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->address));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->address));
+ if (ndr_get_array_length(ndr, &r->address) > ndr_get_array_size(ndr, &r->address)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->address), ndr_get_array_length(ndr, &r->address));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->address), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->address, ndr_get_array_length(ndr, &r->address), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_address_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaTransportInfo0(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaTransportInfo0 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaTransportInfo0");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "quality_of_service", r->quality_of_service);
+ ndr_print_uint32(ndr, "vc_count", r->vc_count);
+ ndr_print_ptr(ndr, "name", r->name);
+ ndr->depth++;
+ if (r->name) {
+ ndr_print_string(ndr, "name", r->name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "address", r->address);
+ ndr->depth++;
+ if (r->address) {
+ ndr_print_string(ndr, "address", r->address);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "wan_link", r->wan_link);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaTransportCtr0(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_NetWkstaTransportCtr0 *r)
+{
+ uint32_t cntr_array_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->array));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ for (cntr_array_1 = 0; cntr_array_1 < r->count; cntr_array_1++) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaTransportInfo0(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < r->count; cntr_array_1++) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaTransportInfo0(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaTransportCtr0(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_NetWkstaTransportCtr0 *r)
+{
+ uint32_t _ptr_array;
+ uint32_t cntr_array_1;
+ TALLOC_CTX *_mem_save_array_0;
+ TALLOC_CTX *_mem_save_array_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_array));
+ if (_ptr_array) {
+ NDR_PULL_ALLOC(ndr, r->array);
+ } else {
+ r->array = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ _mem_save_array_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->array));
+ NDR_PULL_ALLOC_N(ndr, r->array, ndr_get_array_size(ndr, &r->array));
+ _mem_save_array_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+ for (cntr_array_1 = 0; cntr_array_1 < r->count; cntr_array_1++) {
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaTransportInfo0(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < r->count; cntr_array_1++) {
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaTransportInfo0(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_0, 0);
+ }
+ if (r->array) {
+ NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->array, r->count));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaTransportCtr0(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaTransportCtr0 *r)
+{
+ uint32_t cntr_array_1;
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaTransportCtr0");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "count", r->count);
+ ndr_print_ptr(ndr, "array", r->array);
+ ndr->depth++;
+ if (r->array) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "array", r->count);
+ ndr->depth++;
+ for (cntr_array_1=0;cntr_array_1<r->count;cntr_array_1++) {
+ char *idx_1=NULL;
+ asprintf(&idx_1, "[%d]", cntr_array_1);
+ if (idx_1) {
+ ndr_print_wkssvc_NetWkstaTransportInfo0(ndr, "array", &r->array[cntr_array_1]);
+ free(idx_1);
+ }
+ }
+ ndr->depth--;
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaTransportCtr(struct ndr_push *ndr, int ndr_flags, const union wkssvc_NetWkstaTransportCtr *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, level));
+ switch (level) {
+ case 0:
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->ctr0));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 0:
+ if (r->ctr0) {
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaTransportCtr0(ndr, NDR_SCALARS|NDR_BUFFERS, r->ctr0));
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaTransportCtr(struct ndr_pull *ndr, int ndr_flags, union wkssvc_NetWkstaTransportCtr *r)
+{
+ int level;
+ uint32_t _level;
+ TALLOC_CTX *_mem_save_ctr0_0;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
+ if (_level != level) {
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u for wkssvc_NetWkstaTransportCtr", _level);
+ }
+ switch (level) {
+ case 0: {
+ uint32_t _ptr_ctr0;
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_ctr0));
+ if (_ptr_ctr0) {
+ NDR_PULL_ALLOC(ndr, r->ctr0);
+ } else {
+ r->ctr0 = NULL;
+ }
+ break; }
+
+ default: {
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 0:
+ if (r->ctr0) {
+ _mem_save_ctr0_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->ctr0, 0);
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaTransportCtr0(ndr, NDR_SCALARS|NDR_BUFFERS, r->ctr0));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_ctr0_0, 0);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaTransportCtr(struct ndr_print *ndr, const char *name, const union wkssvc_NetWkstaTransportCtr *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "wkssvc_NetWkstaTransportCtr");
+ switch (level) {
+ case 0:
+ ndr_print_ptr(ndr, "ctr0", r->ctr0);
+ ndr->depth++;
+ if (r->ctr0) {
+ ndr_print_wkssvc_NetWkstaTransportCtr0(ndr, "ctr0", r->ctr0);
+ }
+ ndr->depth--;
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+NTSTATUS ndr_push_wkssvc_PasswordBuffer(struct ndr_push *ndr, int ndr_flags, const struct wkssvc_PasswordBuffer *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 1));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->data, 524));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_PasswordBuffer(struct ndr_pull *ndr, int ndr_flags, struct wkssvc_PasswordBuffer *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 1));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->data, 524));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_PasswordBuffer(struct ndr_print *ndr, const char *name, const struct wkssvc_PasswordBuffer *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_PasswordBuffer");
+ ndr->depth++;
+ ndr_print_array_uint8(ndr, "data", r->data, 524);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_joinflags(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_joinflags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_joinflags(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_DEFER_SPN", WKSSVC_JOIN_FLAGS_DEFER_SPN, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED", WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_JOIN_UNSECURE", WKSSVC_JOIN_FLAGS_JOIN_UNSECURE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED", WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_WIN9X_UPGRADE", WKSSVC_JOIN_FLAGS_WIN9X_UPGRADE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE", WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE", WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_JOIN_TYPE", WKSSVC_JOIN_FLAGS_JOIN_TYPE, r);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_renameflags(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_renameflags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_renameflags(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE", WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE, r);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaGetInfo(struct ndr_push *ndr, int flags, const struct wkssvc_NetWkstaGetInfo *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.level));
+ }
+ if (flags & NDR_OUT) {
+ if (r->out.info == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_set_switch_value(ndr, r->out.info, r->in.level));
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaGetInfo(struct ndr_pull *ndr, int flags, struct wkssvc_NetWkstaGetInfo *r)
+{
+ uint32_t _ptr_server_name;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_info_0;
+ if (flags & NDR_IN) {
+ ZERO_STRUCT(r->out);
+
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.level));
+ NDR_PULL_ALLOC(ndr, r->out.info);
+ ZERO_STRUCTP(r->out.info);
+ }
+ if (flags & NDR_OUT) {
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.info);
+ }
+ _mem_save_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.info, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, r->out.info, r->in.level));
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaGetInfo *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaGetInfo");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetWkstaGetInfo");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "level", r->in.level);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetWkstaGetInfo");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "info", r->out.info);
+ ndr->depth++;
+ ndr_print_set_switch_value(ndr, r->out.info, r->in.level);
+ ndr_print_wkssvc_NetWkstaInfo(ndr, "info", r->out.info);
+ ndr->depth--;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaSetInfo(struct ndr_push *ndr, int flags, const struct wkssvc_NetWkstaSetInfo *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.level));
+ if (r->in.info == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_set_switch_value(ndr, r->in.info, r->in.level));
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaInfo(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.info));
+ if (r->in.parm_error == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->in.parm_error));
+ }
+ if (flags & NDR_OUT) {
+ if (r->out.parm_error == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.parm_error));
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaSetInfo(struct ndr_pull *ndr, int flags, struct wkssvc_NetWkstaSetInfo *r)
+{
+ uint32_t _ptr_server_name;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_info_0;
+ TALLOC_CTX *_mem_save_parm_error_0;
+ if (flags & NDR_IN) {
+ ZERO_STRUCT(r->out);
+
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.level));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.info);
+ }
+ _mem_save_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.info, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, r->in.info, r->in.level));
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaInfo(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.info));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, LIBNDR_FLAG_REF_ALLOC);
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.parm_error);
+ }
+ _mem_save_parm_error_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.parm_error, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->in.parm_error));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parm_error_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_PULL_ALLOC(ndr, r->out.parm_error);
+ *r->out.parm_error = *r->in.parm_error;
+ }
+ if (flags & NDR_OUT) {
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.parm_error);
+ }
+ _mem_save_parm_error_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.parm_error, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.parm_error));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parm_error_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaSetInfo *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaSetInfo");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetWkstaSetInfo");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "level", r->in.level);
+ ndr_print_ptr(ndr, "info", r->in.info);
+ ndr->depth++;
+ ndr_print_set_switch_value(ndr, r->in.info, r->in.level);
+ ndr_print_wkssvc_NetWkstaInfo(ndr, "info", r->in.info);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "parm_error", r->in.parm_error);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "parm_error", *r->in.parm_error);
+ ndr->depth--;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetWkstaSetInfo");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "parm_error", r->out.parm_error);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "parm_error", *r->out.parm_error);
+ ndr->depth--;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaEnumUsers(struct ndr_push *ndr, int flags, const struct wkssvc_NetWkstaEnumUsers *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.level));
+ if (r->in.users == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_WKS_USER_ENUM_UNION(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.users));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.prefmaxlen));
+ if (r->in.resumehandle == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->in.resumehandle));
+ }
+ if (flags & NDR_OUT) {
+ if (r->out.users == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_WKS_USER_ENUM_UNION(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.users));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->out.entriesread));
+ if (r->out.entriesread) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.entriesread));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->out.totalentries));
+ if (r->out.totalentries) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.totalentries));
+ }
+ if (r->out.resumehandle == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.resumehandle));
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaEnumUsers(struct ndr_pull *ndr, int flags, struct wkssvc_NetWkstaEnumUsers *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_entriesread;
+ uint32_t _ptr_totalentries;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_users_0;
+ TALLOC_CTX *_mem_save_entriesread_0;
+ TALLOC_CTX *_mem_save_totalentries_0;
+ TALLOC_CTX *_mem_save_resumehandle_0;
+ if (flags & NDR_IN) {
+ ZERO_STRUCT(r->out);
+
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.level));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.users);
+ }
+ _mem_save_users_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.users, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WKS_USER_ENUM_UNION(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.users));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_users_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.prefmaxlen));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.resumehandle);
+ }
+ _mem_save_resumehandle_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.resumehandle, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->in.resumehandle));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_resumehandle_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_PULL_ALLOC(ndr, r->out.users);
+ *r->out.users = *r->in.users;
+ NDR_PULL_ALLOC(ndr, r->out.resumehandle);
+ *r->out.resumehandle = *r->in.resumehandle;
+ }
+ if (flags & NDR_OUT) {
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.users);
+ }
+ _mem_save_users_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.users, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WKS_USER_ENUM_UNION(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.users));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_users_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_entriesread));
+ if (_ptr_entriesread) {
+ NDR_PULL_ALLOC(ndr, r->out.entriesread);
+ } else {
+ r->out.entriesread = NULL;
+ }
+ if (r->out.entriesread) {
+ _mem_save_entriesread_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.entriesread, 0);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.entriesread));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_entriesread_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_totalentries));
+ if (_ptr_totalentries) {
+ NDR_PULL_ALLOC(ndr, r->out.totalentries);
+ } else {
+ r->out.totalentries = NULL;
+ }
+ if (r->out.totalentries) {
+ _mem_save_totalentries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.totalentries, 0);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.totalentries));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_totalentries_0, 0);
+ }
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.resumehandle);
+ }
+ _mem_save_resumehandle_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.resumehandle, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.resumehandle));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_resumehandle_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaEnumUsers(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaEnumUsers *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaEnumUsers");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetWkstaEnumUsers");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "level", r->in.level);
+ ndr_print_ptr(ndr, "users", r->in.users);
+ ndr->depth++;
+ ndr_print_WKS_USER_ENUM_UNION(ndr, "users", r->in.users);
+ ndr->depth--;
+ ndr_print_uint32(ndr, "prefmaxlen", r->in.prefmaxlen);
+ ndr_print_ptr(ndr, "resumehandle", r->in.resumehandle);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "resumehandle", *r->in.resumehandle);
+ ndr->depth--;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetWkstaEnumUsers");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "users", r->out.users);
+ ndr->depth++;
+ ndr_print_WKS_USER_ENUM_UNION(ndr, "users", r->out.users);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "entriesread", r->out.entriesread);
+ ndr->depth++;
+ if (r->out.entriesread) {
+ ndr_print_uint32(ndr, "entriesread", *r->out.entriesread);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "totalentries", r->out.totalentries);
+ ndr->depth++;
+ if (r->out.totalentries) {
+ ndr_print_uint32(ndr, "totalentries", *r->out.totalentries);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "resumehandle", r->out.resumehandle);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "resumehandle", *r->out.resumehandle);
+ ndr->depth--;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRWKSTAUSERGETINFO(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRWKSTAUSERGETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRWKSTAUSERGETINFO(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRWKSTAUSERGETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRWKSTAUSERGETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTAUSERGETINFO *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRWKSTAUSERGETINFO");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRWKSTAUSERGETINFO");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRWKSTAUSERGETINFO");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRWKSTAUSERSETINFO(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRWKSTAUSERSETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRWKSTAUSERSETINFO(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRWKSTAUSERSETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRWKSTAUSERSETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTAUSERSETINFO *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRWKSTAUSERSETINFO");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRWKSTAUSERSETINFO");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRWKSTAUSERSETINFO");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetWkstaTransportEnum(struct ndr_push *ndr, int flags, const struct wkssvc_NetWkstaTransportEnum *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->in.level == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->in.level));
+ if (r->in.ctr == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_set_switch_value(ndr, r->in.ctr, *r->in.level));
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaTransportCtr(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.ctr));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.max_buffer));
+ if (r->in.resume_handle == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->in.resume_handle));
+ }
+ if (flags & NDR_OUT) {
+ if (r->out.level == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.level));
+ if (r->out.ctr == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_set_switch_value(ndr, r->out.ctr, *r->out.level));
+ NDR_CHECK(ndr_push_wkssvc_NetWkstaTransportCtr(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.ctr));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->out.totalentries));
+ if (r->out.totalentries) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.totalentries));
+ }
+ if (r->out.resume_handle == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, *r->out.resume_handle));
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetWkstaTransportEnum(struct ndr_pull *ndr, int flags, struct wkssvc_NetWkstaTransportEnum *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_totalentries;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_level_0;
+ TALLOC_CTX *_mem_save_ctr_0;
+ TALLOC_CTX *_mem_save_totalentries_0;
+ TALLOC_CTX *_mem_save_resume_handle_0;
+ if (flags & NDR_IN) {
+ ZERO_STRUCT(r->out);
+
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.level);
+ }
+ _mem_save_level_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.level, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->in.level));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_level_0, LIBNDR_FLAG_REF_ALLOC);
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.ctr);
+ }
+ _mem_save_ctr_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.ctr, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, r->in.ctr, *r->in.level));
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaTransportCtr(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.ctr));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_ctr_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.max_buffer));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->in.resume_handle);
+ }
+ _mem_save_resume_handle_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.resume_handle, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->in.resume_handle));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_resume_handle_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_PULL_ALLOC(ndr, r->out.level);
+ *r->out.level = *r->in.level;
+ NDR_PULL_ALLOC(ndr, r->out.ctr);
+ *r->out.ctr = *r->in.ctr;
+ NDR_PULL_ALLOC(ndr, r->out.resume_handle);
+ *r->out.resume_handle = *r->in.resume_handle;
+ }
+ if (flags & NDR_OUT) {
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.level);
+ }
+ _mem_save_level_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.level, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.level));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_level_0, LIBNDR_FLAG_REF_ALLOC);
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.ctr);
+ }
+ _mem_save_ctr_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.ctr, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, r->out.ctr, *r->out.level));
+ NDR_CHECK(ndr_pull_wkssvc_NetWkstaTransportCtr(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.ctr));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_ctr_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_totalentries));
+ if (_ptr_totalentries) {
+ NDR_PULL_ALLOC(ndr, r->out.totalentries);
+ } else {
+ r->out.totalentries = NULL;
+ }
+ if (r->out.totalentries) {
+ _mem_save_totalentries_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.totalentries, 0);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.totalentries));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_totalentries_0, 0);
+ }
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.resume_handle);
+ }
+ _mem_save_resume_handle_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->out.resume_handle, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.resume_handle));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_resume_handle_0, LIBNDR_FLAG_REF_ALLOC);
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetWkstaTransportEnum(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaTransportEnum *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetWkstaTransportEnum");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetWkstaTransportEnum");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "level", r->in.level);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "level", *r->in.level);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "ctr", r->in.ctr);
+ ndr->depth++;
+ ndr_print_set_switch_value(ndr, r->in.ctr, *r->in.level);
+ ndr_print_wkssvc_NetWkstaTransportCtr(ndr, "ctr", r->in.ctr);
+ ndr->depth--;
+ ndr_print_uint32(ndr, "max_buffer", r->in.max_buffer);
+ ndr_print_ptr(ndr, "resume_handle", r->in.resume_handle);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "resume_handle", *r->in.resume_handle);
+ ndr->depth--;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetWkstaTransportEnum");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "level", r->out.level);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "level", *r->out.level);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "ctr", r->out.ctr);
+ ndr->depth++;
+ ndr_print_set_switch_value(ndr, r->out.ctr, *r->out.level);
+ ndr_print_wkssvc_NetWkstaTransportCtr(ndr, "ctr", r->out.ctr);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "totalentries", r->out.totalentries);
+ ndr->depth++;
+ if (r->out.totalentries) {
+ ndr_print_uint32(ndr, "totalentries", *r->out.totalentries);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "resume_handle", r->out.resume_handle);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "resume_handle", *r->out.resume_handle);
+ ndr->depth--;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRWKSTATRANSPORTADD(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRWKSTATRANSPORTADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRWKSTATRANSPORTADD(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRWKSTATRANSPORTADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRWKSTATRANSPORTADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTATRANSPORTADD *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRWKSTATRANSPORTADD");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRWKSTATRANSPORTADD");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRWKSTATRANSPORTADD");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRWKSTATRANSPORTDEL(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRWKSTATRANSPORTDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRWKSTATRANSPORTDEL(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRWKSTATRANSPORTDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRWKSTATRANSPORTDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTATRANSPORTDEL *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRWKSTATRANSPORTDEL");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRWKSTATRANSPORTDEL");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRWKSTATRANSPORTDEL");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRUSEADD(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRUSEADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRUSEADD(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRUSEADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRUSEADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEADD *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRUSEADD");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRUSEADD");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRUSEADD");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRUSEGETINFO(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRUSEGETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRUSEGETINFO(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRUSEGETINFO *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRUSEGETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEGETINFO *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRUSEGETINFO");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRUSEGETINFO");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRUSEGETINFO");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRUSEDEL(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRUSEDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRUSEDEL(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRUSEDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRUSEDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEDEL *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRUSEDEL");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRUSEDEL");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRUSEDEL");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRUSEENUM(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRUSEENUM *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRUSEENUM(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRUSEENUM *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRUSEENUM(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEENUM *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRUSEENUM");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRUSEENUM");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRUSEENUM");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRMESSAGEBUFFERSEND(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRMESSAGEBUFFERSEND *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRMESSAGEBUFFERSEND(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRMESSAGEBUFFERSEND *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRMESSAGEBUFFERSEND(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRMESSAGEBUFFERSEND *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRMESSAGEBUFFERSEND");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRMESSAGEBUFFERSEND");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRMESSAGEBUFFERSEND");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRWORKSTATIONSTATISTICSGET");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRWORKSTATIONSTATISTICSGET");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRWORKSTATIONSTATISTICSGET");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRLOGONDOMAINNAMEADD(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEADD(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRLOGONDOMAINNAMEADD *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRLOGONDOMAINNAMEADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEADD *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRLOGONDOMAINNAMEADD");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRLOGONDOMAINNAMEADD");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRLOGONDOMAINNAMEADD");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRLOGONDOMAINNAMEDEL");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRLOGONDOMAINNAMEDEL");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRLOGONDOMAINNAMEDEL");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRJOINDOMAIN(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRJOINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRJOINDOMAIN(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRJOINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRJOINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRJOINDOMAIN *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRJOINDOMAIN");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRJOINDOMAIN");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRJOINDOMAIN");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRUNJOINDOMAIN(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRUNJOINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRUNJOINDOMAIN(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRUNJOINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRUNJOINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUNJOINDOMAIN *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRUNJOINDOMAIN");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRUNJOINDOMAIN");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRUNJOINDOMAIN");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRRENAMEMACHINEINDOMAIN");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRRENAMEMACHINEINDOMAIN");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRRENAMEMACHINEINDOMAIN");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRVALIDATENAME(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRVALIDATENAME *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRVALIDATENAME(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRVALIDATENAME *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRVALIDATENAME(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRVALIDATENAME *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRVALIDATENAME");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRVALIDATENAME");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRVALIDATENAME");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRGETJOININFORMATION(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRGETJOININFORMATION *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRGETJOININFORMATION(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRGETJOININFORMATION *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRGETJOININFORMATION(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOININFORMATION *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRGETJOININFORMATION");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRGETJOININFORMATION");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRGETJOININFORMATION");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRGETJOINABLEOUS(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRGETJOINABLEOUS *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRGETJOINABLEOUS(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRGETJOINABLEOUS *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRGETJOINABLEOUS(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOINABLEOUS *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRGETJOINABLEOUS");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRGETJOINABLEOUS");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRGETJOINABLEOUS");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetrJoinDomain2(struct ndr_push *ndr, int flags, const struct wkssvc_NetrJoinDomain2 *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ if (r->in.domain_name == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.domain_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.domain_name, ndr_charset_length(r->in.domain_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.account_name));
+ if (r->in.account_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.account_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.account_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.account_name, ndr_charset_length(r->in.account_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.admin_account));
+ if (r->in.admin_account) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.admin_account, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.admin_account, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.admin_account, ndr_charset_length(r->in.admin_account, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.encrypted_password));
+ if (r->in.encrypted_password) {
+ NDR_CHECK(ndr_push_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.encrypted_password));
+ }
+ NDR_CHECK(ndr_push_wkssvc_joinflags(ndr, NDR_SCALARS, r->in.join_flags));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetrJoinDomain2(struct ndr_pull *ndr, int flags, struct wkssvc_NetrJoinDomain2 *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_account_name;
+ uint32_t _ptr_admin_account;
+ uint32_t _ptr_encrypted_password;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_account_name_0;
+ TALLOC_CTX *_mem_save_admin_account_0;
+ TALLOC_CTX *_mem_save_encrypted_password_0;
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.domain_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.domain_name));
+ if (ndr_get_array_length(ndr, &r->in.domain_name) > ndr_get_array_size(ndr, &r->in.domain_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.domain_name), ndr_get_array_length(ndr, &r->in.domain_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.domain_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.domain_name, ndr_get_array_length(ndr, &r->in.domain_name), sizeof(uint16_t), CH_UTF16));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_account_name));
+ if (_ptr_account_name) {
+ NDR_PULL_ALLOC(ndr, r->in.account_name);
+ } else {
+ r->in.account_name = NULL;
+ }
+ if (r->in.account_name) {
+ _mem_save_account_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.account_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.account_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.account_name));
+ if (ndr_get_array_length(ndr, &r->in.account_name) > ndr_get_array_size(ndr, &r->in.account_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.account_name), ndr_get_array_length(ndr, &r->in.account_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.account_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.account_name, ndr_get_array_length(ndr, &r->in.account_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_account_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_admin_account));
+ if (_ptr_admin_account) {
+ NDR_PULL_ALLOC(ndr, r->in.admin_account);
+ } else {
+ r->in.admin_account = NULL;
+ }
+ if (r->in.admin_account) {
+ _mem_save_admin_account_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.admin_account, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.admin_account));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.admin_account));
+ if (ndr_get_array_length(ndr, &r->in.admin_account) > ndr_get_array_size(ndr, &r->in.admin_account)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.admin_account), ndr_get_array_length(ndr, &r->in.admin_account));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.admin_account), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.admin_account, ndr_get_array_length(ndr, &r->in.admin_account), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_admin_account_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_encrypted_password));
+ if (_ptr_encrypted_password) {
+ NDR_PULL_ALLOC(ndr, r->in.encrypted_password);
+ } else {
+ r->in.encrypted_password = NULL;
+ }
+ if (r->in.encrypted_password) {
+ _mem_save_encrypted_password_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.encrypted_password, 0);
+ NDR_CHECK(ndr_pull_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.encrypted_password));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_encrypted_password_0, 0);
+ }
+ NDR_CHECK(ndr_pull_wkssvc_joinflags(ndr, NDR_SCALARS, &r->in.join_flags));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetrJoinDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrJoinDomain2 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetrJoinDomain2");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetrJoinDomain2");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "domain_name", r->in.domain_name);
+ ndr->depth++;
+ ndr_print_string(ndr, "domain_name", r->in.domain_name);
+ ndr->depth--;
+ ndr_print_ptr(ndr, "account_name", r->in.account_name);
+ ndr->depth++;
+ if (r->in.account_name) {
+ ndr_print_string(ndr, "account_name", r->in.account_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "admin_account", r->in.admin_account);
+ ndr->depth++;
+ if (r->in.admin_account) {
+ ndr_print_string(ndr, "admin_account", r->in.admin_account);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "encrypted_password", r->in.encrypted_password);
+ ndr->depth++;
+ if (r->in.encrypted_password) {
+ ndr_print_wkssvc_PasswordBuffer(ndr, "encrypted_password", r->in.encrypted_password);
+ }
+ ndr->depth--;
+ ndr_print_wkssvc_joinflags(ndr, "join_flags", r->in.join_flags);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetrJoinDomain2");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetrUnjoinDomain2(struct ndr_push *ndr, int flags, const struct wkssvc_NetrUnjoinDomain2 *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.account));
+ if (r->in.account) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.account, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.account, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.account, ndr_charset_length(r->in.account, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.encrypted_password));
+ if (r->in.encrypted_password) {
+ NDR_CHECK(ndr_push_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.encrypted_password));
+ }
+ NDR_CHECK(ndr_push_wkssvc_joinflags(ndr, NDR_SCALARS, r->in.unjoin_flags));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetrUnjoinDomain2(struct ndr_pull *ndr, int flags, struct wkssvc_NetrUnjoinDomain2 *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_account;
+ uint32_t _ptr_encrypted_password;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_account_0;
+ TALLOC_CTX *_mem_save_encrypted_password_0;
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_account));
+ if (_ptr_account) {
+ NDR_PULL_ALLOC(ndr, r->in.account);
+ } else {
+ r->in.account = NULL;
+ }
+ if (r->in.account) {
+ _mem_save_account_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.account, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.account));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.account));
+ if (ndr_get_array_length(ndr, &r->in.account) > ndr_get_array_size(ndr, &r->in.account)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.account), ndr_get_array_length(ndr, &r->in.account));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.account), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.account, ndr_get_array_length(ndr, &r->in.account), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_account_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_encrypted_password));
+ if (_ptr_encrypted_password) {
+ NDR_PULL_ALLOC(ndr, r->in.encrypted_password);
+ } else {
+ r->in.encrypted_password = NULL;
+ }
+ if (r->in.encrypted_password) {
+ _mem_save_encrypted_password_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.encrypted_password, 0);
+ NDR_CHECK(ndr_pull_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.encrypted_password));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_encrypted_password_0, 0);
+ }
+ NDR_CHECK(ndr_pull_wkssvc_joinflags(ndr, NDR_SCALARS, &r->in.unjoin_flags));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetrUnjoinDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrUnjoinDomain2 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetrUnjoinDomain2");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetrUnjoinDomain2");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "account", r->in.account);
+ ndr->depth++;
+ if (r->in.account) {
+ ndr_print_string(ndr, "account", r->in.account);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "encrypted_password", r->in.encrypted_password);
+ ndr->depth++;
+ if (r->in.encrypted_password) {
+ ndr_print_wkssvc_PasswordBuffer(ndr, "encrypted_password", r->in.encrypted_password);
+ }
+ ndr->depth--;
+ ndr_print_wkssvc_joinflags(ndr, "unjoin_flags", r->in.unjoin_flags);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetrUnjoinDomain2");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetrRenameMachineInDomain2(struct ndr_push *ndr, int flags, const struct wkssvc_NetrRenameMachineInDomain2 *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.NewMachineName));
+ if (r->in.NewMachineName) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.NewMachineName, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.NewMachineName, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.NewMachineName, ndr_charset_length(r->in.NewMachineName, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.Account));
+ if (r->in.Account) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.Account, ndr_charset_length(r->in.Account, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.EncryptedPassword));
+ if (r->in.EncryptedPassword) {
+ NDR_CHECK(ndr_push_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ }
+ NDR_CHECK(ndr_push_wkssvc_renameflags(ndr, NDR_SCALARS, r->in.RenameOptions));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetrRenameMachineInDomain2(struct ndr_pull *ndr, int flags, struct wkssvc_NetrRenameMachineInDomain2 *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_NewMachineName;
+ uint32_t _ptr_Account;
+ uint32_t _ptr_EncryptedPassword;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_NewMachineName_0;
+ TALLOC_CTX *_mem_save_Account_0;
+ TALLOC_CTX *_mem_save_EncryptedPassword_0;
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_NewMachineName));
+ if (_ptr_NewMachineName) {
+ NDR_PULL_ALLOC(ndr, r->in.NewMachineName);
+ } else {
+ r->in.NewMachineName = NULL;
+ }
+ if (r->in.NewMachineName) {
+ _mem_save_NewMachineName_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.NewMachineName, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.NewMachineName));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.NewMachineName));
+ if (ndr_get_array_length(ndr, &r->in.NewMachineName) > ndr_get_array_size(ndr, &r->in.NewMachineName)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.NewMachineName), ndr_get_array_length(ndr, &r->in.NewMachineName));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.NewMachineName), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.NewMachineName, ndr_get_array_length(ndr, &r->in.NewMachineName), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_NewMachineName_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_Account));
+ if (_ptr_Account) {
+ NDR_PULL_ALLOC(ndr, r->in.Account);
+ } else {
+ r->in.Account = NULL;
+ }
+ if (r->in.Account) {
+ _mem_save_Account_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.Account, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.Account));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.Account));
+ if (ndr_get_array_length(ndr, &r->in.Account) > ndr_get_array_size(ndr, &r->in.Account)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.Account), ndr_get_array_length(ndr, &r->in.Account));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.Account, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_Account_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_EncryptedPassword));
+ if (_ptr_EncryptedPassword) {
+ NDR_PULL_ALLOC(ndr, r->in.EncryptedPassword);
+ } else {
+ r->in.EncryptedPassword = NULL;
+ }
+ if (r->in.EncryptedPassword) {
+ _mem_save_EncryptedPassword_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.EncryptedPassword, 0);
+ NDR_CHECK(ndr_pull_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_EncryptedPassword_0, 0);
+ }
+ NDR_CHECK(ndr_pull_wkssvc_renameflags(ndr, NDR_SCALARS, &r->in.RenameOptions));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetrRenameMachineInDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrRenameMachineInDomain2 *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetrRenameMachineInDomain2");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetrRenameMachineInDomain2");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "NewMachineName", r->in.NewMachineName);
+ ndr->depth++;
+ if (r->in.NewMachineName) {
+ ndr_print_string(ndr, "NewMachineName", r->in.NewMachineName);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "Account", r->in.Account);
+ ndr->depth++;
+ if (r->in.Account) {
+ ndr_print_string(ndr, "Account", r->in.Account);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ ndr->depth++;
+ if (r->in.EncryptedPassword) {
+ ndr_print_wkssvc_PasswordBuffer(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ }
+ ndr->depth--;
+ ndr_print_wkssvc_renameflags(ndr, "RenameOptions", r->in.RenameOptions);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetrRenameMachineInDomain2");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRVALIDATENAME2(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRVALIDATENAME2 *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRVALIDATENAME2(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRVALIDATENAME2 *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRVALIDATENAME2(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRVALIDATENAME2 *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRVALIDATENAME2");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRVALIDATENAME2");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRVALIDATENAME2");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRGETJOINABLEOUS2(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRGETJOINABLEOUS2 *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRGETJOINABLEOUS2(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRGETJOINABLEOUS2 *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRGETJOINABLEOUS2(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOINABLEOUS2 *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRGETJOINABLEOUS2");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRGETJOINABLEOUS2");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRGETJOINABLEOUS2");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetrAddAlternateComputerName(struct ndr_push *ndr, int flags, const struct wkssvc_NetrAddAlternateComputerName *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.NewAlternateMachineName));
+ if (r->in.NewAlternateMachineName) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.NewAlternateMachineName, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.NewAlternateMachineName, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.NewAlternateMachineName, ndr_charset_length(r->in.NewAlternateMachineName, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.Account));
+ if (r->in.Account) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.Account, ndr_charset_length(r->in.Account, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.EncryptedPassword));
+ if (r->in.EncryptedPassword) {
+ NDR_CHECK(ndr_push_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.Reserved));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetrAddAlternateComputerName(struct ndr_pull *ndr, int flags, struct wkssvc_NetrAddAlternateComputerName *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_NewAlternateMachineName;
+ uint32_t _ptr_Account;
+ uint32_t _ptr_EncryptedPassword;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_NewAlternateMachineName_0;
+ TALLOC_CTX *_mem_save_Account_0;
+ TALLOC_CTX *_mem_save_EncryptedPassword_0;
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_NewAlternateMachineName));
+ if (_ptr_NewAlternateMachineName) {
+ NDR_PULL_ALLOC(ndr, r->in.NewAlternateMachineName);
+ } else {
+ r->in.NewAlternateMachineName = NULL;
+ }
+ if (r->in.NewAlternateMachineName) {
+ _mem_save_NewAlternateMachineName_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.NewAlternateMachineName, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.NewAlternateMachineName));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.NewAlternateMachineName));
+ if (ndr_get_array_length(ndr, &r->in.NewAlternateMachineName) > ndr_get_array_size(ndr, &r->in.NewAlternateMachineName)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.NewAlternateMachineName), ndr_get_array_length(ndr, &r->in.NewAlternateMachineName));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.NewAlternateMachineName), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.NewAlternateMachineName, ndr_get_array_length(ndr, &r->in.NewAlternateMachineName), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_NewAlternateMachineName_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_Account));
+ if (_ptr_Account) {
+ NDR_PULL_ALLOC(ndr, r->in.Account);
+ } else {
+ r->in.Account = NULL;
+ }
+ if (r->in.Account) {
+ _mem_save_Account_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.Account, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.Account));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.Account));
+ if (ndr_get_array_length(ndr, &r->in.Account) > ndr_get_array_size(ndr, &r->in.Account)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.Account), ndr_get_array_length(ndr, &r->in.Account));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.Account, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_Account_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_EncryptedPassword));
+ if (_ptr_EncryptedPassword) {
+ NDR_PULL_ALLOC(ndr, r->in.EncryptedPassword);
+ } else {
+ r->in.EncryptedPassword = NULL;
+ }
+ if (r->in.EncryptedPassword) {
+ _mem_save_EncryptedPassword_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.EncryptedPassword, 0);
+ NDR_CHECK(ndr_pull_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_EncryptedPassword_0, 0);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.Reserved));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetrAddAlternateComputerName(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrAddAlternateComputerName *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetrAddAlternateComputerName");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetrAddAlternateComputerName");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "NewAlternateMachineName", r->in.NewAlternateMachineName);
+ ndr->depth++;
+ if (r->in.NewAlternateMachineName) {
+ ndr_print_string(ndr, "NewAlternateMachineName", r->in.NewAlternateMachineName);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "Account", r->in.Account);
+ ndr->depth++;
+ if (r->in.Account) {
+ ndr_print_string(ndr, "Account", r->in.Account);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ ndr->depth++;
+ if (r->in.EncryptedPassword) {
+ ndr_print_wkssvc_PasswordBuffer(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "Reserved", r->in.Reserved);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetrAddAlternateComputerName");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_wkssvc_NetrRemoveAlternateComputerName(struct ndr_push *ndr, int flags, const struct wkssvc_NetrRemoveAlternateComputerName *r)
+{
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.server_name));
+ if (r->in.server_name) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.server_name, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.server_name, ndr_charset_length(r->in.server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.AlternateMachineNameToRemove));
+ if (r->in.AlternateMachineNameToRemove) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.AlternateMachineNameToRemove, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.AlternateMachineNameToRemove, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.AlternateMachineNameToRemove, ndr_charset_length(r->in.AlternateMachineNameToRemove, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.Account));
+ if (r->in.Account) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->in.Account, CH_UTF16)));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->in.Account, ndr_charset_length(r->in.Account, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+ }
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.EncryptedPassword));
+ if (r->in.EncryptedPassword) {
+ NDR_CHECK(ndr_push_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->in.Reserved));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_wkssvc_NetrRemoveAlternateComputerName(struct ndr_pull *ndr, int flags, struct wkssvc_NetrRemoveAlternateComputerName *r)
+{
+ uint32_t _ptr_server_name;
+ uint32_t _ptr_AlternateMachineNameToRemove;
+ uint32_t _ptr_Account;
+ uint32_t _ptr_EncryptedPassword;
+ TALLOC_CTX *_mem_save_server_name_0;
+ TALLOC_CTX *_mem_save_AlternateMachineNameToRemove_0;
+ TALLOC_CTX *_mem_save_Account_0;
+ TALLOC_CTX *_mem_save_EncryptedPassword_0;
+ if (flags & NDR_IN) {
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+ if (_ptr_server_name) {
+ NDR_PULL_ALLOC(ndr, r->in.server_name);
+ } else {
+ r->in.server_name = NULL;
+ }
+ if (r->in.server_name) {
+ _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.server_name, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.server_name));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.server_name));
+ if (ndr_get_array_length(ndr, &r->in.server_name) > ndr_get_array_size(ndr, &r->in.server_name)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.server_name), ndr_get_array_length(ndr, &r->in.server_name));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.server_name, ndr_get_array_length(ndr, &r->in.server_name), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_AlternateMachineNameToRemove));
+ if (_ptr_AlternateMachineNameToRemove) {
+ NDR_PULL_ALLOC(ndr, r->in.AlternateMachineNameToRemove);
+ } else {
+ r->in.AlternateMachineNameToRemove = NULL;
+ }
+ if (r->in.AlternateMachineNameToRemove) {
+ _mem_save_AlternateMachineNameToRemove_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.AlternateMachineNameToRemove, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.AlternateMachineNameToRemove));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.AlternateMachineNameToRemove));
+ if (ndr_get_array_length(ndr, &r->in.AlternateMachineNameToRemove) > ndr_get_array_size(ndr, &r->in.AlternateMachineNameToRemove)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.AlternateMachineNameToRemove), ndr_get_array_length(ndr, &r->in.AlternateMachineNameToRemove));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.AlternateMachineNameToRemove), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.AlternateMachineNameToRemove, ndr_get_array_length(ndr, &r->in.AlternateMachineNameToRemove), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_AlternateMachineNameToRemove_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_Account));
+ if (_ptr_Account) {
+ NDR_PULL_ALLOC(ndr, r->in.Account);
+ } else {
+ r->in.Account = NULL;
+ }
+ if (r->in.Account) {
+ _mem_save_Account_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.Account, 0);
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->in.Account));
+ NDR_CHECK(ndr_pull_array_length(ndr, &r->in.Account));
+ if (ndr_get_array_length(ndr, &r->in.Account) > ndr_get_array_size(ndr, &r->in.Account)) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->in.Account), ndr_get_array_length(ndr, &r->in.Account));
+ }
+ NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t)));
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.Account, ndr_get_array_length(ndr, &r->in.Account), sizeof(uint16_t), CH_UTF16));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_Account_0, 0);
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_EncryptedPassword));
+ if (_ptr_EncryptedPassword) {
+ NDR_PULL_ALLOC(ndr, r->in.EncryptedPassword);
+ } else {
+ r->in.EncryptedPassword = NULL;
+ }
+ if (r->in.EncryptedPassword) {
+ _mem_save_EncryptedPassword_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->in.EncryptedPassword, 0);
+ NDR_CHECK(ndr_pull_wkssvc_PasswordBuffer(ndr, NDR_SCALARS, r->in.EncryptedPassword));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_EncryptedPassword_0, 0);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.Reserved));
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_wkssvc_NetrRemoveAlternateComputerName(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrRemoveAlternateComputerName *r)
+{
+ ndr_print_struct(ndr, name, "wkssvc_NetrRemoveAlternateComputerName");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "wkssvc_NetrRemoveAlternateComputerName");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "server_name", r->in.server_name);
+ ndr->depth++;
+ if (r->in.server_name) {
+ ndr_print_string(ndr, "server_name", r->in.server_name);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "AlternateMachineNameToRemove", r->in.AlternateMachineNameToRemove);
+ ndr->depth++;
+ if (r->in.AlternateMachineNameToRemove) {
+ ndr_print_string(ndr, "AlternateMachineNameToRemove", r->in.AlternateMachineNameToRemove);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "Account", r->in.Account);
+ ndr->depth++;
+ if (r->in.Account) {
+ ndr_print_string(ndr, "Account", r->in.Account);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ ndr->depth++;
+ if (r->in.EncryptedPassword) {
+ ndr_print_wkssvc_PasswordBuffer(ndr, "EncryptedPassword", r->in.EncryptedPassword);
+ }
+ ndr->depth--;
+ ndr_print_uint32(ndr, "Reserved", r->in.Reserved);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "wkssvc_NetrRemoveAlternateComputerName");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRSETPRIMARYCOMPUTERNAME");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRSETPRIMARYCOMPUTERNAME");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRSETPRIMARYCOMPUTERNAME");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct ndr_push *ndr, int flags, const struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct ndr_pull *ndr, int flags, struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r)
+{
+ if (flags & NDR_IN) {
+ }
+ if (flags & NDR_OUT) {
+ NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result));
+ }
+ return NT_STATUS_OK;
+}
+
+_PUBLIC_ void ndr_print_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r)
+{
+ ndr_print_struct(ndr, name, "WKSSVC_NETRENUMERATECOMPUTERNAMES");
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ ndr_print_struct(ndr, "in", "WKSSVC_NETRENUMERATECOMPUTERNAMES");
+ ndr->depth++;
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "WKSSVC_NETRENUMERATECOMPUTERNAMES");
+ ndr->depth++;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+const struct dcerpc_interface_call wkssvc_calls[] = {
+ {
+ "wkssvc_NetWkstaGetInfo",
+ sizeof(struct wkssvc_NetWkstaGetInfo),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetWkstaGetInfo,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetWkstaGetInfo,
+ (ndr_print_function_t) ndr_print_wkssvc_NetWkstaGetInfo,
+ False,
+ },
+ {
+ "wkssvc_NetWkstaSetInfo",
+ sizeof(struct wkssvc_NetWkstaSetInfo),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetWkstaSetInfo,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetWkstaSetInfo,
+ (ndr_print_function_t) ndr_print_wkssvc_NetWkstaSetInfo,
+ False,
+ },
+ {
+ "wkssvc_NetWkstaEnumUsers",
+ sizeof(struct wkssvc_NetWkstaEnumUsers),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetWkstaEnumUsers,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetWkstaEnumUsers,
+ (ndr_print_function_t) ndr_print_wkssvc_NetWkstaEnumUsers,
+ False,
+ },
+ {
+ "WKSSVC_NETRWKSTAUSERGETINFO",
+ sizeof(struct WKSSVC_NETRWKSTAUSERGETINFO),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRWKSTAUSERGETINFO,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRWKSTAUSERGETINFO,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRWKSTAUSERGETINFO,
+ False,
+ },
+ {
+ "WKSSVC_NETRWKSTAUSERSETINFO",
+ sizeof(struct WKSSVC_NETRWKSTAUSERSETINFO),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRWKSTAUSERSETINFO,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRWKSTAUSERSETINFO,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRWKSTAUSERSETINFO,
+ False,
+ },
+ {
+ "wkssvc_NetWkstaTransportEnum",
+ sizeof(struct wkssvc_NetWkstaTransportEnum),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetWkstaTransportEnum,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetWkstaTransportEnum,
+ (ndr_print_function_t) ndr_print_wkssvc_NetWkstaTransportEnum,
+ False,
+ },
+ {
+ "WKSSVC_NETRWKSTATRANSPORTADD",
+ sizeof(struct WKSSVC_NETRWKSTATRANSPORTADD),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRWKSTATRANSPORTADD,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRWKSTATRANSPORTADD,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRWKSTATRANSPORTADD,
+ False,
+ },
+ {
+ "WKSSVC_NETRWKSTATRANSPORTDEL",
+ sizeof(struct WKSSVC_NETRWKSTATRANSPORTDEL),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRWKSTATRANSPORTDEL,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRWKSTATRANSPORTDEL,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRWKSTATRANSPORTDEL,
+ False,
+ },
+ {
+ "WKSSVC_NETRUSEADD",
+ sizeof(struct WKSSVC_NETRUSEADD),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRUSEADD,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRUSEADD,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRUSEADD,
+ False,
+ },
+ {
+ "WKSSVC_NETRUSEGETINFO",
+ sizeof(struct WKSSVC_NETRUSEGETINFO),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRUSEGETINFO,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRUSEGETINFO,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRUSEGETINFO,
+ False,
+ },
+ {
+ "WKSSVC_NETRUSEDEL",
+ sizeof(struct WKSSVC_NETRUSEDEL),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRUSEDEL,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRUSEDEL,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRUSEDEL,
+ False,
+ },
+ {
+ "WKSSVC_NETRUSEENUM",
+ sizeof(struct WKSSVC_NETRUSEENUM),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRUSEENUM,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRUSEENUM,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRUSEENUM,
+ False,
+ },
+ {
+ "WKSSVC_NETRMESSAGEBUFFERSEND",
+ sizeof(struct WKSSVC_NETRMESSAGEBUFFERSEND),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRMESSAGEBUFFERSEND,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRMESSAGEBUFFERSEND,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRMESSAGEBUFFERSEND,
+ False,
+ },
+ {
+ "WKSSVC_NETRWORKSTATIONSTATISTICSGET",
+ sizeof(struct WKSSVC_NETRWORKSTATIONSTATISTICSGET),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRWORKSTATIONSTATISTICSGET,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRWORKSTATIONSTATISTICSGET,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRWORKSTATIONSTATISTICSGET,
+ False,
+ },
+ {
+ "WKSSVC_NETRLOGONDOMAINNAMEADD",
+ sizeof(struct WKSSVC_NETRLOGONDOMAINNAMEADD),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRLOGONDOMAINNAMEADD,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEADD,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRLOGONDOMAINNAMEADD,
+ False,
+ },
+ {
+ "WKSSVC_NETRLOGONDOMAINNAMEDEL",
+ sizeof(struct WKSSVC_NETRLOGONDOMAINNAMEDEL),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRLOGONDOMAINNAMEDEL,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEDEL,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRLOGONDOMAINNAMEDEL,
+ False,
+ },
+ {
+ "WKSSVC_NETRJOINDOMAIN",
+ sizeof(struct WKSSVC_NETRJOINDOMAIN),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRJOINDOMAIN,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRJOINDOMAIN,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRJOINDOMAIN,
+ False,
+ },
+ {
+ "WKSSVC_NETRUNJOINDOMAIN",
+ sizeof(struct WKSSVC_NETRUNJOINDOMAIN),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRUNJOINDOMAIN,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRUNJOINDOMAIN,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRUNJOINDOMAIN,
+ False,
+ },
+ {
+ "WKSSVC_NETRRENAMEMACHINEINDOMAIN",
+ sizeof(struct WKSSVC_NETRRENAMEMACHINEINDOMAIN),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRRENAMEMACHINEINDOMAIN,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRRENAMEMACHINEINDOMAIN,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRRENAMEMACHINEINDOMAIN,
+ False,
+ },
+ {
+ "WKSSVC_NETRVALIDATENAME",
+ sizeof(struct WKSSVC_NETRVALIDATENAME),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRVALIDATENAME,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRVALIDATENAME,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRVALIDATENAME,
+ False,
+ },
+ {
+ "WKSSVC_NETRGETJOININFORMATION",
+ sizeof(struct WKSSVC_NETRGETJOININFORMATION),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRGETJOININFORMATION,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRGETJOININFORMATION,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRGETJOININFORMATION,
+ False,
+ },
+ {
+ "WKSSVC_NETRGETJOINABLEOUS",
+ sizeof(struct WKSSVC_NETRGETJOINABLEOUS),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRGETJOINABLEOUS,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRGETJOINABLEOUS,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRGETJOINABLEOUS,
+ False,
+ },
+ {
+ "wkssvc_NetrJoinDomain2",
+ sizeof(struct wkssvc_NetrJoinDomain2),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetrJoinDomain2,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetrJoinDomain2,
+ (ndr_print_function_t) ndr_print_wkssvc_NetrJoinDomain2,
+ False,
+ },
+ {
+ "wkssvc_NetrUnjoinDomain2",
+ sizeof(struct wkssvc_NetrUnjoinDomain2),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetrUnjoinDomain2,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetrUnjoinDomain2,
+ (ndr_print_function_t) ndr_print_wkssvc_NetrUnjoinDomain2,
+ False,
+ },
+ {
+ "wkssvc_NetrRenameMachineInDomain2",
+ sizeof(struct wkssvc_NetrRenameMachineInDomain2),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetrRenameMachineInDomain2,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetrRenameMachineInDomain2,
+ (ndr_print_function_t) ndr_print_wkssvc_NetrRenameMachineInDomain2,
+ False,
+ },
+ {
+ "WKSSVC_NETRVALIDATENAME2",
+ sizeof(struct WKSSVC_NETRVALIDATENAME2),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRVALIDATENAME2,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRVALIDATENAME2,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRVALIDATENAME2,
+ False,
+ },
+ {
+ "WKSSVC_NETRGETJOINABLEOUS2",
+ sizeof(struct WKSSVC_NETRGETJOINABLEOUS2),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRGETJOINABLEOUS2,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRGETJOINABLEOUS2,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRGETJOINABLEOUS2,
+ False,
+ },
+ {
+ "wkssvc_NetrAddAlternateComputerName",
+ sizeof(struct wkssvc_NetrAddAlternateComputerName),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetrAddAlternateComputerName,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetrAddAlternateComputerName,
+ (ndr_print_function_t) ndr_print_wkssvc_NetrAddAlternateComputerName,
+ False,
+ },
+ {
+ "wkssvc_NetrRemoveAlternateComputerName",
+ sizeof(struct wkssvc_NetrRemoveAlternateComputerName),
+ (ndr_push_flags_fn_t) ndr_push_wkssvc_NetrRemoveAlternateComputerName,
+ (ndr_pull_flags_fn_t) ndr_pull_wkssvc_NetrRemoveAlternateComputerName,
+ (ndr_print_function_t) ndr_print_wkssvc_NetrRemoveAlternateComputerName,
+ False,
+ },
+ {
+ "WKSSVC_NETRSETPRIMARYCOMPUTERNAME",
+ sizeof(struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRSETPRIMARYCOMPUTERNAME,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRSETPRIMARYCOMPUTERNAME,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRSETPRIMARYCOMPUTERNAME,
+ False,
+ },
+ {
+ "WKSSVC_NETRENUMERATECOMPUTERNAMES",
+ sizeof(struct WKSSVC_NETRENUMERATECOMPUTERNAMES),
+ (ndr_push_flags_fn_t) ndr_push_WKSSVC_NETRENUMERATECOMPUTERNAMES,
+ (ndr_pull_flags_fn_t) ndr_pull_WKSSVC_NETRENUMERATECOMPUTERNAMES,
+ (ndr_print_function_t) ndr_print_WKSSVC_NETRENUMERATECOMPUTERNAMES,
+ False,
+ },
+ { NULL, 0, NULL, NULL, NULL, False }
+};
+
+const char * const wkssvc_endpoint_strings[] = {
+ "ncacn_np:[\\pipe\\wkssvc]",
+};
+
+const struct dcerpc_endpoint_list wkssvc_endpoints = {
+ .count = 1,
+ .names = wkssvc_endpoint_strings
+};
+
+const char * const wkssvc_authservice_strings[] = {
+ "host",
+};
+
+const struct dcerpc_authservice_list wkssvc_authservices = {
+ .count = 1,
+ .names = wkssvc_authservice_strings
+};
+
+
+const struct dcerpc_interface_table dcerpc_table_wkssvc = {
+ .name = "wkssvc",
+ .syntax_id = {
+ {0x6bffd098,0xa112,0x3610,{0x98,0x33},{0x46,0xc3,0xf8,0x7e,0x34,0x5a}},
+ DCERPC_WKSSVC_VERSION
+ },
+ .helpstring = DCERPC_WKSSVC_HELPSTRING,
+ .num_calls = 31,
+ .calls = wkssvc_calls,
+ .endpoints = &wkssvc_endpoints,
+ .authservices = &wkssvc_authservices
+};
+
diff --git a/source/librpc/gen_ndr/ndr_wkssvc.h b/source/librpc/gen_ndr/ndr_wkssvc.h
new file mode 100644
index 00000000000..69ed5c86fd6
--- /dev/null
+++ b/source/librpc/gen_ndr/ndr_wkssvc.h
@@ -0,0 +1,133 @@
+/* header auto-generated by pidl */
+
+#include "librpc/gen_ndr/wkssvc.h"
+
+#ifndef _HEADER_NDR_wkssvc
+#define _HEADER_NDR_wkssvc
+
+#include "librpc/ndr/libndr.h"
+#define DCERPC_WKSSVC_UUID "6bffd098-a112-3610-9833-46c3f87e345a"
+#define DCERPC_WKSSVC_VERSION 1.0
+#define DCERPC_WKSSVC_NAME "wkssvc"
+#define DCERPC_WKSSVC_HELPSTRING "Workstation Service"
+extern const struct dcerpc_interface_table dcerpc_table_wkssvc;
+NTSTATUS dcerpc_server_wkssvc_init(void);
+#define DCERPC_WKSSVC_NETWKSTAGETINFO (0x00)
+
+#define DCERPC_WKSSVC_NETWKSTASETINFO (0x01)
+
+#define DCERPC_WKSSVC_NETWKSTAENUMUSERS (0x02)
+
+#define DCERPC_WKSSVC_NETRWKSTAUSERGETINFO (0x03)
+
+#define DCERPC_WKSSVC_NETRWKSTAUSERSETINFO (0x04)
+
+#define DCERPC_WKSSVC_NETWKSTATRANSPORTENUM (0x05)
+
+#define DCERPC_WKSSVC_NETRWKSTATRANSPORTADD (0x06)
+
+#define DCERPC_WKSSVC_NETRWKSTATRANSPORTDEL (0x07)
+
+#define DCERPC_WKSSVC_NETRUSEADD (0x08)
+
+#define DCERPC_WKSSVC_NETRUSEGETINFO (0x09)
+
+#define DCERPC_WKSSVC_NETRUSEDEL (0x0a)
+
+#define DCERPC_WKSSVC_NETRUSEENUM (0x0b)
+
+#define DCERPC_WKSSVC_NETRMESSAGEBUFFERSEND (0x0c)
+
+#define DCERPC_WKSSVC_NETRWORKSTATIONSTATISTICSGET (0x0d)
+
+#define DCERPC_WKSSVC_NETRLOGONDOMAINNAMEADD (0x0e)
+
+#define DCERPC_WKSSVC_NETRLOGONDOMAINNAMEDEL (0x0f)
+
+#define DCERPC_WKSSVC_NETRJOINDOMAIN (0x10)
+
+#define DCERPC_WKSSVC_NETRUNJOINDOMAIN (0x11)
+
+#define DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN (0x12)
+
+#define DCERPC_WKSSVC_NETRVALIDATENAME (0x13)
+
+#define DCERPC_WKSSVC_NETRGETJOININFORMATION (0x14)
+
+#define DCERPC_WKSSVC_NETRGETJOINABLEOUS (0x15)
+
+#define DCERPC_WKSSVC_NETRJOINDOMAIN2 (0x16)
+
+#define DCERPC_WKSSVC_NETRUNJOINDOMAIN2 (0x17)
+
+#define DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN2 (0x18)
+
+#define DCERPC_WKSSVC_NETRVALIDATENAME2 (0x19)
+
+#define DCERPC_WKSSVC_NETRGETJOINABLEOUS2 (0x1a)
+
+#define DCERPC_WKSSVC_NETRADDALTERNATECOMPUTERNAME (0x1b)
+
+#define DCERPC_WKSSVC_NETRREMOVEALTERNATECOMPUTERNAME (0x1c)
+
+#define DCERPC_WKSSVC_NETRSETPRIMARYCOMPUTERNAME (0x1d)
+
+#define DCERPC_WKSSVC_NETRENUMERATECOMPUTERNAMES (0x1e)
+
+#define DCERPC_WKSSVC_CALL_COUNT (31)
+void ndr_print_wkssvc_NetWkstaInfo100(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo100 *r);
+void ndr_print_wkssvc_NetWkstaInfo101(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo101 *r);
+void ndr_print_wkssvc_NetWkstaInfo102(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo102 *r);
+void ndr_print_wkssvc_NetWkstaInfo502(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo502 *r);
+void ndr_print_wkssvc_NetWkstaInfo1010(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1010 *r);
+void ndr_print_wkssvc_NetWkstaInfo1011(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1011 *r);
+void ndr_print_wkssvc_NetWkstaInfo1012(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1012 *r);
+void ndr_print_wkssvc_NetWkstaInfo1013(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1013 *r);
+void ndr_print_wkssvc_NetWkstaInfo1018(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1018 *r);
+void ndr_print_wkssvc_NetWkstaInfo1023(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1023 *r);
+void ndr_print_wkssvc_NetWkstaInfo1027(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1027 *r);
+void ndr_print_wkssvc_NetWkstaInfo1033(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaInfo1033 *r);
+void ndr_print_wkssvc_NetWkstaInfo(struct ndr_print *ndr, const char *name, const union wkssvc_NetWkstaInfo *r);
+void ndr_print_USER_INFO_0(struct ndr_print *ndr, const char *name, const struct USER_INFO_0 *r);
+void ndr_print_USER_INFO_0_CONTAINER(struct ndr_print *ndr, const char *name, const struct USER_INFO_0_CONTAINER *r);
+void ndr_print_USER_INFO_1(struct ndr_print *ndr, const char *name, const struct USER_INFO_1 *r);
+void ndr_print_USER_INFO_1_CONTAINER(struct ndr_print *ndr, const char *name, const struct USER_INFO_1_CONTAINER *r);
+void ndr_print_WKS_USER_ENUM_UNION(struct ndr_print *ndr, const char *name, const union WKS_USER_ENUM_UNION *r);
+void ndr_print_wkssvc_NetWkstaTransportInfo0(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaTransportInfo0 *r);
+void ndr_print_wkssvc_NetWkstaTransportCtr0(struct ndr_print *ndr, const char *name, const struct wkssvc_NetWkstaTransportCtr0 *r);
+void ndr_print_wkssvc_NetWkstaTransportCtr(struct ndr_print *ndr, const char *name, const union wkssvc_NetWkstaTransportCtr *r);
+void ndr_print_wkssvc_PasswordBuffer(struct ndr_print *ndr, const char *name, const struct wkssvc_PasswordBuffer *r);
+void ndr_print_wkssvc_joinflags(struct ndr_print *ndr, const char *name, uint32_t r);
+void ndr_print_wkssvc_renameflags(struct ndr_print *ndr, const char *name, uint32_t r);
+void ndr_print_wkssvc_NetWkstaGetInfo(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaGetInfo *r);
+void ndr_print_wkssvc_NetWkstaSetInfo(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaSetInfo *r);
+void ndr_print_wkssvc_NetWkstaEnumUsers(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaEnumUsers *r);
+void ndr_print_WKSSVC_NETRWKSTAUSERGETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTAUSERGETINFO *r);
+void ndr_print_WKSSVC_NETRWKSTAUSERSETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTAUSERSETINFO *r);
+void ndr_print_wkssvc_NetWkstaTransportEnum(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetWkstaTransportEnum *r);
+void ndr_print_WKSSVC_NETRWKSTATRANSPORTADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTATRANSPORTADD *r);
+void ndr_print_WKSSVC_NETRWKSTATRANSPORTDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWKSTATRANSPORTDEL *r);
+void ndr_print_WKSSVC_NETRUSEADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEADD *r);
+void ndr_print_WKSSVC_NETRUSEGETINFO(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEGETINFO *r);
+void ndr_print_WKSSVC_NETRUSEDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEDEL *r);
+void ndr_print_WKSSVC_NETRUSEENUM(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUSEENUM *r);
+void ndr_print_WKSSVC_NETRMESSAGEBUFFERSEND(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRMESSAGEBUFFERSEND *r);
+void ndr_print_WKSSVC_NETRWORKSTATIONSTATISTICSGET(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r);
+void ndr_print_WKSSVC_NETRLOGONDOMAINNAMEADD(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEADD *r);
+void ndr_print_WKSSVC_NETRLOGONDOMAINNAMEDEL(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r);
+void ndr_print_WKSSVC_NETRJOINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRJOINDOMAIN *r);
+void ndr_print_WKSSVC_NETRUNJOINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRUNJOINDOMAIN *r);
+void ndr_print_WKSSVC_NETRRENAMEMACHINEINDOMAIN(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r);
+void ndr_print_WKSSVC_NETRVALIDATENAME(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRVALIDATENAME *r);
+void ndr_print_WKSSVC_NETRGETJOININFORMATION(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOININFORMATION *r);
+void ndr_print_WKSSVC_NETRGETJOINABLEOUS(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOINABLEOUS *r);
+void ndr_print_wkssvc_NetrJoinDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrJoinDomain2 *r);
+void ndr_print_wkssvc_NetrUnjoinDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrUnjoinDomain2 *r);
+void ndr_print_wkssvc_NetrRenameMachineInDomain2(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrRenameMachineInDomain2 *r);
+void ndr_print_WKSSVC_NETRVALIDATENAME2(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRVALIDATENAME2 *r);
+void ndr_print_WKSSVC_NETRGETJOINABLEOUS2(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRGETJOINABLEOUS2 *r);
+void ndr_print_wkssvc_NetrAddAlternateComputerName(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrAddAlternateComputerName *r);
+void ndr_print_wkssvc_NetrRemoveAlternateComputerName(struct ndr_print *ndr, const char *name, int flags, const struct wkssvc_NetrRemoveAlternateComputerName *r);
+void ndr_print_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r);
+void ndr_print_WKSSVC_NETRENUMERATECOMPUTERNAMES(struct ndr_print *ndr, const char *name, int flags, const struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r);
+#endif /* _HEADER_NDR_wkssvc */
diff --git a/source/librpc/gen_ndr/notify.h b/source/librpc/gen_ndr/notify.h
new file mode 100644
index 00000000000..f85b9b1bac8
--- /dev/null
+++ b/source/librpc/gen_ndr/notify.h
@@ -0,0 +1,33 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_notify
+#define _HEADER_notify
+
+struct notify_entry {
+ struct server_id server;
+ uint32_t filter;
+ uint32_t subdir_filter;
+ const char * path;/* [flag(LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM)] */
+ uint32_t path_len;
+ void* private_data;
+}/* [public] */;
+
+struct notify_depth {
+ uint32_t max_mask;
+ uint32_t max_mask_subdir;
+ uint32_t num_entries;
+ struct notify_entry *entries;
+};
+
+struct notify_array {
+ uint32_t num_depths;
+ struct notify_depth *depth;
+}/* [public] */;
+
+struct notify_event {
+ uint32_t action;
+ const char * path;/* [flag(LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM)] */
+ void* private_data;
+}/* [public] */;
+
+#endif /* _HEADER_notify */
diff --git a/source/librpc/gen_ndr/security.h b/source/librpc/gen_ndr/security.h
new file mode 100644
index 00000000000..1c51af5b9ca
--- /dev/null
+++ b/source/librpc/gen_ndr/security.h
@@ -0,0 +1 @@
+#include "ndr/security.h"
diff --git a/source/librpc/gen_ndr/srv_wkssvc.c b/source/librpc/gen_ndr/srv_wkssvc.c
new file mode 100644
index 00000000000..d0535d41c94
--- /dev/null
+++ b/source/librpc/gen_ndr/srv_wkssvc.c
@@ -0,0 +1,2073 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * server auto-generated by pidl. DO NOT MODIFY!
+ */
+
+#include "includes.h"
+#include "librpc/gen_ndr/srv_wkssvc.h"
+
+static BOOL api_wkssvc_NetWkstaGetInfo(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetWkstaGetInfo r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetWkstaGetInfo");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetWkstaGetInfo(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaGetInfo, &r);
+
+ ZERO_STRUCT(r.out);
+ r.out.info = talloc_zero(mem_ctx, union wkssvc_NetWkstaInfo);
+ if (r.out.info == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ r.out.result = _wkssvc_NetWkstaGetInfo(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaGetInfo, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetWkstaGetInfo(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetWkstaSetInfo(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetWkstaSetInfo r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetWkstaSetInfo");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetWkstaSetInfo(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaSetInfo, &r);
+
+ ZERO_STRUCT(r.out);
+ r.out.parm_error = r.in.parm_error;
+ r.out.result = _wkssvc_NetWkstaSetInfo(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaSetInfo, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetWkstaSetInfo(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetWkstaEnumUsers(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetWkstaEnumUsers r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetWkstaEnumUsers");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetWkstaEnumUsers(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaEnumUsers, &r);
+
+ ZERO_STRUCT(r.out);
+ r.out.users = r.in.users;
+ r.out.entriesread = talloc_zero(mem_ctx, uint32_t);
+ if (r.out.entriesread == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ r.out.totalentries = talloc_zero(mem_ctx, uint32_t);
+ if (r.out.totalentries == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ r.out.resumehandle = r.in.resumehandle;
+ r.out.result = _wkssvc_NetWkstaEnumUsers(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaEnumUsers, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetWkstaEnumUsers(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRWKSTAUSERGETINFO(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRWKSTAUSERGETINFO r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRWKSTAUSERGETINFO");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRWKSTAUSERGETINFO(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTAUSERGETINFO, &r);
+
+ r.out.result = _WKSSVC_NETRWKSTAUSERGETINFO(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTAUSERGETINFO, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRWKSTAUSERGETINFO(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRWKSTAUSERSETINFO(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRWKSTAUSERSETINFO r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRWKSTAUSERSETINFO");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRWKSTAUSERSETINFO(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTAUSERSETINFO, &r);
+
+ r.out.result = _WKSSVC_NETRWKSTAUSERSETINFO(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTAUSERSETINFO, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRWKSTAUSERSETINFO(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetWkstaTransportEnum(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetWkstaTransportEnum r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetWkstaTransportEnum");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetWkstaTransportEnum(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetWkstaTransportEnum, &r);
+
+ ZERO_STRUCT(r.out);
+ r.out.level = r.in.level;
+ r.out.ctr = r.in.ctr;
+ r.out.totalentries = talloc_zero(mem_ctx, uint32_t);
+ if (r.out.totalentries == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ r.out.resume_handle = r.in.resume_handle;
+ r.out.result = _wkssvc_NetWkstaTransportEnum(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetWkstaTransportEnum, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetWkstaTransportEnum(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRWKSTATRANSPORTADD(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRWKSTATRANSPORTADD r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRWKSTATRANSPORTADD");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRWKSTATRANSPORTADD(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTATRANSPORTADD, &r);
+
+ r.out.result = _WKSSVC_NETRWKSTATRANSPORTADD(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTATRANSPORTADD, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRWKSTATRANSPORTADD(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRWKSTATRANSPORTDEL(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRWKSTATRANSPORTDEL r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRWKSTATRANSPORTDEL");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRWKSTATRANSPORTDEL(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWKSTATRANSPORTDEL, &r);
+
+ r.out.result = _WKSSVC_NETRWKSTATRANSPORTDEL(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWKSTATRANSPORTDEL, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRWKSTATRANSPORTDEL(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRUSEADD(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRUSEADD r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRUSEADD");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRUSEADD(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEADD, &r);
+
+ r.out.result = _WKSSVC_NETRUSEADD(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEADD, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRUSEADD(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRUSEGETINFO(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRUSEGETINFO r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRUSEGETINFO");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRUSEGETINFO(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEGETINFO, &r);
+
+ r.out.result = _WKSSVC_NETRUSEGETINFO(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEGETINFO, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRUSEGETINFO(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRUSEDEL(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRUSEDEL r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRUSEDEL");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRUSEDEL(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEDEL, &r);
+
+ r.out.result = _WKSSVC_NETRUSEDEL(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEDEL, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRUSEDEL(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRUSEENUM(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRUSEENUM r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRUSEENUM");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRUSEENUM(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUSEENUM, &r);
+
+ r.out.result = _WKSSVC_NETRUSEENUM(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUSEENUM, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRUSEENUM(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRMESSAGEBUFFERSEND(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRMESSAGEBUFFERSEND r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRMESSAGEBUFFERSEND");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRMESSAGEBUFFERSEND(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRMESSAGEBUFFERSEND, &r);
+
+ r.out.result = _WKSSVC_NETRMESSAGEBUFFERSEND(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRMESSAGEBUFFERSEND, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRMESSAGEBUFFERSEND(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRWORKSTATIONSTATISTICSGET(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRWORKSTATIONSTATISTICSGET r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRWORKSTATIONSTATISTICSGET");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRWORKSTATIONSTATISTICSGET(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRWORKSTATIONSTATISTICSGET, &r);
+
+ r.out.result = _WKSSVC_NETRWORKSTATIONSTATISTICSGET(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRWORKSTATIONSTATISTICSGET, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRWORKSTATIONSTATISTICSGET(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRLOGONDOMAINNAMEADD(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRLOGONDOMAINNAMEADD r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRLOGONDOMAINNAMEADD");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEADD(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEADD, &r);
+
+ r.out.result = _WKSSVC_NETRLOGONDOMAINNAMEADD(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEADD, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRLOGONDOMAINNAMEADD(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRLOGONDOMAINNAMEDEL(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRLOGONDOMAINNAMEDEL r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRLOGONDOMAINNAMEDEL");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRLOGONDOMAINNAMEDEL(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEDEL, &r);
+
+ r.out.result = _WKSSVC_NETRLOGONDOMAINNAMEDEL(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRLOGONDOMAINNAMEDEL, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRLOGONDOMAINNAMEDEL(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRJOINDOMAIN(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRJOINDOMAIN r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRJOINDOMAIN");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRJOINDOMAIN(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRJOINDOMAIN, &r);
+
+ r.out.result = _WKSSVC_NETRJOINDOMAIN(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRJOINDOMAIN, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRJOINDOMAIN(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRUNJOINDOMAIN(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRUNJOINDOMAIN r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRUNJOINDOMAIN");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRUNJOINDOMAIN(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRUNJOINDOMAIN, &r);
+
+ r.out.result = _WKSSVC_NETRUNJOINDOMAIN(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRUNJOINDOMAIN, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRUNJOINDOMAIN(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRRENAMEMACHINEINDOMAIN(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRRENAMEMACHINEINDOMAIN r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRRENAMEMACHINEINDOMAIN");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRRENAMEMACHINEINDOMAIN(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRRENAMEMACHINEINDOMAIN, &r);
+
+ r.out.result = _WKSSVC_NETRRENAMEMACHINEINDOMAIN(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRRENAMEMACHINEINDOMAIN, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRRENAMEMACHINEINDOMAIN(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRVALIDATENAME(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRVALIDATENAME r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRVALIDATENAME");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRVALIDATENAME(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRVALIDATENAME, &r);
+
+ r.out.result = _WKSSVC_NETRVALIDATENAME(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRVALIDATENAME, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRVALIDATENAME(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRGETJOININFORMATION(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRGETJOININFORMATION r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRGETJOININFORMATION");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRGETJOININFORMATION(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOININFORMATION, &r);
+
+ r.out.result = _WKSSVC_NETRGETJOININFORMATION(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOININFORMATION, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRGETJOININFORMATION(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRGETJOINABLEOUS(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRGETJOINABLEOUS r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRGETJOINABLEOUS");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRGETJOINABLEOUS(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOINABLEOUS, &r);
+
+ r.out.result = _WKSSVC_NETRGETJOINABLEOUS(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOINABLEOUS, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRGETJOINABLEOUS(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetrJoinDomain2(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetrJoinDomain2 r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetrJoinDomain2");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetrJoinDomain2(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrJoinDomain2, &r);
+
+ r.out.result = _wkssvc_NetrJoinDomain2(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrJoinDomain2, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetrJoinDomain2(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetrUnjoinDomain2(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetrUnjoinDomain2 r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetrUnjoinDomain2");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetrUnjoinDomain2(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrUnjoinDomain2, &r);
+
+ r.out.result = _wkssvc_NetrUnjoinDomain2(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrUnjoinDomain2, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetrUnjoinDomain2(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetrRenameMachineInDomain2(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetrRenameMachineInDomain2 r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetrRenameMachineInDomain2");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetrRenameMachineInDomain2(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrRenameMachineInDomain2, &r);
+
+ r.out.result = _wkssvc_NetrRenameMachineInDomain2(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrRenameMachineInDomain2, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetrRenameMachineInDomain2(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRVALIDATENAME2(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRVALIDATENAME2 r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRVALIDATENAME2");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRVALIDATENAME2(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRVALIDATENAME2, &r);
+
+ r.out.result = _WKSSVC_NETRVALIDATENAME2(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRVALIDATENAME2, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRVALIDATENAME2(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRGETJOINABLEOUS2(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRGETJOINABLEOUS2 r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRGETJOINABLEOUS2");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRGETJOINABLEOUS2(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRGETJOINABLEOUS2, &r);
+
+ r.out.result = _WKSSVC_NETRGETJOINABLEOUS2(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRGETJOINABLEOUS2, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRGETJOINABLEOUS2(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetrAddAlternateComputerName(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetrAddAlternateComputerName r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetrAddAlternateComputerName");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetrAddAlternateComputerName(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrAddAlternateComputerName, &r);
+
+ r.out.result = _wkssvc_NetrAddAlternateComputerName(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrAddAlternateComputerName, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetrAddAlternateComputerName(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct wkssvc_NetrRemoveAlternateComputerName r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_wkssvc_NetrRemoveAlternateComputerName");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_wkssvc_NetrRemoveAlternateComputerName(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(wkssvc_NetrRemoveAlternateComputerName, &r);
+
+ r.out.result = _wkssvc_NetrRemoveAlternateComputerName(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(wkssvc_NetrRemoveAlternateComputerName, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_wkssvc_NetrRemoveAlternateComputerName(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRSETPRIMARYCOMPUTERNAME");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRSETPRIMARYCOMPUTERNAME, &r);
+
+ r.out.result = _WKSSVC_NETRSETPRIMARYCOMPUTERNAME(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRSETPRIMARYCOMPUTERNAME, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRSETPRIMARYCOMPUTERNAME(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+static BOOL api_WKSSVC_NETRENUMERATECOMPUTERNAMES(pipes_struct *p)
+{
+ struct ndr_pull *pull;
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB blob;
+ struct WKSSVC_NETRENUMERATECOMPUTERNAMES r;
+ TALLOC_CTX *mem_ctx = talloc_init("api_WKSSVC_NETRENUMERATECOMPUTERNAMES");
+
+ if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = ndr_pull_WKSSVC_NETRENUMERATECOMPUTERNAMES(pull, NDR_IN, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_IN_DEBUG(WKSSVC_NETRENUMERATECOMPUTERNAMES, &r);
+
+ r.out.result = _WKSSVC_NETRENUMERATECOMPUTERNAMES(p, &r);
+
+ if (p->rng_fault_state) {
+ talloc_free(mem_ctx);
+ /* Return True here, srv_pipe_hnd.c will take care */
+ return True;
+ }
+
+ if (DEBUGLEVEL >= 10)
+ NDR_PRINT_OUT_DEBUG(WKSSVC_NETRENUMERATECOMPUTERNAMES, &r);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (push == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = ndr_push_WKSSVC_NETRENUMERATECOMPUTERNAMES(push, NDR_OUT, &r);
+ if (NT_STATUS_IS_ERR(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ blob = ndr_push_blob(push);
+ if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32)blob.length)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+
+ return True;
+}
+
+
+/* Tables */
+static struct api_struct api_wkssvc_cmds[] =
+{
+ {"WKSSVC_NETWKSTAGETINFO", DCERPC_WKSSVC_NETWKSTAGETINFO, api_wkssvc_NetWkstaGetInfo},
+ {"WKSSVC_NETWKSTASETINFO", DCERPC_WKSSVC_NETWKSTASETINFO, api_wkssvc_NetWkstaSetInfo},
+ {"WKSSVC_NETWKSTAENUMUSERS", DCERPC_WKSSVC_NETWKSTAENUMUSERS, api_wkssvc_NetWkstaEnumUsers},
+ {"WKSSVC_NETRWKSTAUSERGETINFO", DCERPC_WKSSVC_NETRWKSTAUSERGETINFO, api_WKSSVC_NETRWKSTAUSERGETINFO},
+ {"WKSSVC_NETRWKSTAUSERSETINFO", DCERPC_WKSSVC_NETRWKSTAUSERSETINFO, api_WKSSVC_NETRWKSTAUSERSETINFO},
+ {"WKSSVC_NETWKSTATRANSPORTENUM", DCERPC_WKSSVC_NETWKSTATRANSPORTENUM, api_wkssvc_NetWkstaTransportEnum},
+ {"WKSSVC_NETRWKSTATRANSPORTADD", DCERPC_WKSSVC_NETRWKSTATRANSPORTADD, api_WKSSVC_NETRWKSTATRANSPORTADD},
+ {"WKSSVC_NETRWKSTATRANSPORTDEL", DCERPC_WKSSVC_NETRWKSTATRANSPORTDEL, api_WKSSVC_NETRWKSTATRANSPORTDEL},
+ {"WKSSVC_NETRUSEADD", DCERPC_WKSSVC_NETRUSEADD, api_WKSSVC_NETRUSEADD},
+ {"WKSSVC_NETRUSEGETINFO", DCERPC_WKSSVC_NETRUSEGETINFO, api_WKSSVC_NETRUSEGETINFO},
+ {"WKSSVC_NETRUSEDEL", DCERPC_WKSSVC_NETRUSEDEL, api_WKSSVC_NETRUSEDEL},
+ {"WKSSVC_NETRUSEENUM", DCERPC_WKSSVC_NETRUSEENUM, api_WKSSVC_NETRUSEENUM},
+ {"WKSSVC_NETRMESSAGEBUFFERSEND", DCERPC_WKSSVC_NETRMESSAGEBUFFERSEND, api_WKSSVC_NETRMESSAGEBUFFERSEND},
+ {"WKSSVC_NETRWORKSTATIONSTATISTICSGET", DCERPC_WKSSVC_NETRWORKSTATIONSTATISTICSGET, api_WKSSVC_NETRWORKSTATIONSTATISTICSGET},
+ {"WKSSVC_NETRLOGONDOMAINNAMEADD", DCERPC_WKSSVC_NETRLOGONDOMAINNAMEADD, api_WKSSVC_NETRLOGONDOMAINNAMEADD},
+ {"WKSSVC_NETRLOGONDOMAINNAMEDEL", DCERPC_WKSSVC_NETRLOGONDOMAINNAMEDEL, api_WKSSVC_NETRLOGONDOMAINNAMEDEL},
+ {"WKSSVC_NETRJOINDOMAIN", DCERPC_WKSSVC_NETRJOINDOMAIN, api_WKSSVC_NETRJOINDOMAIN},
+ {"WKSSVC_NETRUNJOINDOMAIN", DCERPC_WKSSVC_NETRUNJOINDOMAIN, api_WKSSVC_NETRUNJOINDOMAIN},
+ {"WKSSVC_NETRRENAMEMACHINEINDOMAIN", DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN, api_WKSSVC_NETRRENAMEMACHINEINDOMAIN},
+ {"WKSSVC_NETRVALIDATENAME", DCERPC_WKSSVC_NETRVALIDATENAME, api_WKSSVC_NETRVALIDATENAME},
+ {"WKSSVC_NETRGETJOININFORMATION", DCERPC_WKSSVC_NETRGETJOININFORMATION, api_WKSSVC_NETRGETJOININFORMATION},
+ {"WKSSVC_NETRGETJOINABLEOUS", DCERPC_WKSSVC_NETRGETJOINABLEOUS, api_WKSSVC_NETRGETJOINABLEOUS},
+ {"WKSSVC_NETRJOINDOMAIN2", DCERPC_WKSSVC_NETRJOINDOMAIN2, api_wkssvc_NetrJoinDomain2},
+ {"WKSSVC_NETRUNJOINDOMAIN2", DCERPC_WKSSVC_NETRUNJOINDOMAIN2, api_wkssvc_NetrUnjoinDomain2},
+ {"WKSSVC_NETRRENAMEMACHINEINDOMAIN2", DCERPC_WKSSVC_NETRRENAMEMACHINEINDOMAIN2, api_wkssvc_NetrRenameMachineInDomain2},
+ {"WKSSVC_NETRVALIDATENAME2", DCERPC_WKSSVC_NETRVALIDATENAME2, api_WKSSVC_NETRVALIDATENAME2},
+ {"WKSSVC_NETRGETJOINABLEOUS2", DCERPC_WKSSVC_NETRGETJOINABLEOUS2, api_WKSSVC_NETRGETJOINABLEOUS2},
+ {"WKSSVC_NETRADDALTERNATECOMPUTERNAME", DCERPC_WKSSVC_NETRADDALTERNATECOMPUTERNAME, api_wkssvc_NetrAddAlternateComputerName},
+ {"WKSSVC_NETRREMOVEALTERNATECOMPUTERNAME", DCERPC_WKSSVC_NETRREMOVEALTERNATECOMPUTERNAME, api_wkssvc_NetrRemoveAlternateComputerName},
+ {"WKSSVC_NETRSETPRIMARYCOMPUTERNAME", DCERPC_WKSSVC_NETRSETPRIMARYCOMPUTERNAME, api_WKSSVC_NETRSETPRIMARYCOMPUTERNAME},
+ {"WKSSVC_NETRENUMERATECOMPUTERNAMES", DCERPC_WKSSVC_NETRENUMERATECOMPUTERNAMES, api_WKSSVC_NETRENUMERATECOMPUTERNAMES},
+};
+
+void wkssvc_get_pipe_fns(struct api_struct **fns, int *n_fns)
+{
+ *fns = api_wkssvc_cmds;
+ *n_fns = sizeof(api_wkssvc_cmds) / sizeof(struct api_struct);
+}
+
+NTSTATUS rpc_wkssvc_init(void)
+{
+ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "wkssvc", "wkssvc", api_wkssvc_cmds, sizeof(api_wkssvc_cmds) / sizeof(struct api_struct));
+}
diff --git a/source/librpc/gen_ndr/srv_wkssvc.h b/source/librpc/gen_ndr/srv_wkssvc.h
new file mode 100644
index 00000000000..4633152eacd
--- /dev/null
+++ b/source/librpc/gen_ndr/srv_wkssvc.h
@@ -0,0 +1,37 @@
+#include "librpc/gen_ndr/ndr_wkssvc.h"
+#ifndef __SRV_WKSSVC__
+#define __SRV_WKSSVC__
+WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r);
+WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r);
+WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r);
+WERROR _WKSSVC_NETRWKSTAUSERGETINFO(pipes_struct *p, struct WKSSVC_NETRWKSTAUSERGETINFO *r);
+WERROR _WKSSVC_NETRWKSTAUSERSETINFO(pipes_struct *p, struct WKSSVC_NETRWKSTAUSERSETINFO *r);
+WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r);
+WERROR _WKSSVC_NETRWKSTATRANSPORTADD(pipes_struct *p, struct WKSSVC_NETRWKSTATRANSPORTADD *r);
+WERROR _WKSSVC_NETRWKSTATRANSPORTDEL(pipes_struct *p, struct WKSSVC_NETRWKSTATRANSPORTDEL *r);
+WERROR _WKSSVC_NETRUSEADD(pipes_struct *p, struct WKSSVC_NETRUSEADD *r);
+WERROR _WKSSVC_NETRUSEGETINFO(pipes_struct *p, struct WKSSVC_NETRUSEGETINFO *r);
+WERROR _WKSSVC_NETRUSEDEL(pipes_struct *p, struct WKSSVC_NETRUSEDEL *r);
+WERROR _WKSSVC_NETRUSEENUM(pipes_struct *p, struct WKSSVC_NETRUSEENUM *r);
+WERROR _WKSSVC_NETRMESSAGEBUFFERSEND(pipes_struct *p, struct WKSSVC_NETRMESSAGEBUFFERSEND *r);
+WERROR _WKSSVC_NETRWORKSTATIONSTATISTICSGET(pipes_struct *p, struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r);
+WERROR _WKSSVC_NETRLOGONDOMAINNAMEADD(pipes_struct *p, struct WKSSVC_NETRLOGONDOMAINNAMEADD *r);
+WERROR _WKSSVC_NETRLOGONDOMAINNAMEDEL(pipes_struct *p, struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r);
+WERROR _WKSSVC_NETRJOINDOMAIN(pipes_struct *p, struct WKSSVC_NETRJOINDOMAIN *r);
+WERROR _WKSSVC_NETRUNJOINDOMAIN(pipes_struct *p, struct WKSSVC_NETRUNJOINDOMAIN *r);
+WERROR _WKSSVC_NETRRENAMEMACHINEINDOMAIN(pipes_struct *p, struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r);
+WERROR _WKSSVC_NETRVALIDATENAME(pipes_struct *p, struct WKSSVC_NETRVALIDATENAME *r);
+WERROR _WKSSVC_NETRGETJOININFORMATION(pipes_struct *p, struct WKSSVC_NETRGETJOININFORMATION *r);
+WERROR _WKSSVC_NETRGETJOINABLEOUS(pipes_struct *p, struct WKSSVC_NETRGETJOINABLEOUS *r);
+WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r);
+WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p, struct wkssvc_NetrUnjoinDomain2 *r);
+WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r);
+WERROR _WKSSVC_NETRVALIDATENAME2(pipes_struct *p, struct WKSSVC_NETRVALIDATENAME2 *r);
+WERROR _WKSSVC_NETRGETJOINABLEOUS2(pipes_struct *p, struct WKSSVC_NETRGETJOINABLEOUS2 *r);
+WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r);
+WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r);
+WERROR _WKSSVC_NETRSETPRIMARYCOMPUTERNAME(pipes_struct *p, struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r);
+WERROR _WKSSVC_NETRENUMERATECOMPUTERNAMES(pipes_struct *p, struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r);
+void wkssvc_get_pipe_fns(struct api_struct **fns, int *n_fns);
+NTSTATUS rpc_wkssvc_init(void);
+#endif /* __SRV_WKSSVC__ */
diff --git a/source/librpc/gen_ndr/srvsvc.h b/source/librpc/gen_ndr/srvsvc.h
new file mode 100644
index 00000000000..a1519c3ba8a
--- /dev/null
+++ b/source/librpc/gen_ndr/srvsvc.h
@@ -0,0 +1,1753 @@
+/* header auto-generated by pidl */
+
+#include "librpc/gen_ndr/security.h"
+#include "librpc/gen_ndr/svcctl.h"
+#ifndef _HEADER_srvsvc
+#define _HEADER_srvsvc
+
+#define STYPE_TEMPORARY ( 0x40000000 )
+#define STYPE_HIDDEN ( 0x80000000 )
+#define SHARE_1005_CSC_POLICY_MASK ( 0x00000030 )
+#define SHARE_1005_CSC_POLICY_SHIFT ( 4 )
+struct srvsvc_NetCharDevInfo0 {
+ const char *device;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetCharDevCtr0 {
+ uint32_t count;
+ struct srvsvc_NetCharDevInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetCharDevInfo1 {
+ const char *device;/* [unique,charset(UTF16)] */
+ uint32_t status;
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t time;
+};
+
+struct srvsvc_NetCharDevCtr1 {
+ uint32_t count;
+ struct srvsvc_NetCharDevInfo1 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetCharDevInfo {
+ struct srvsvc_NetCharDevInfo0 *info0;/* [unique,case(0)] */
+ struct srvsvc_NetCharDevInfo1 *info1;/* [unique,case] */
+};
+
+union srvsvc_NetCharDevCtr {
+ struct srvsvc_NetCharDevCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetCharDevCtr1 *ctr1;/* [unique,case] */
+};
+
+struct srvsvc_NetCharDevQInfo0 {
+ const char *device;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetCharDevQCtr0 {
+ uint32_t count;
+ struct srvsvc_NetCharDevQInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetCharDevQInfo1 {
+ const char *device;/* [unique,charset(UTF16)] */
+ uint32_t priority;
+ const char *devices;/* [unique,charset(UTF16)] */
+ uint32_t users;
+ uint32_t num_ahead;
+};
+
+struct srvsvc_NetCharDevQCtr1 {
+ uint32_t count;
+ struct srvsvc_NetCharDevQInfo1 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetCharDevQInfo {
+ struct srvsvc_NetCharDevQInfo0 *info0;/* [unique,case(0)] */
+ struct srvsvc_NetCharDevQInfo1 *info1;/* [unique,case] */
+};
+
+union srvsvc_NetCharDevQCtr {
+ struct srvsvc_NetCharDevQCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetCharDevQCtr1 *ctr1;/* [unique,case] */
+};
+
+struct srvsvc_NetConnInfo0 {
+ uint32_t conn_id;
+};
+
+struct srvsvc_NetConnCtr0 {
+ uint32_t count;
+ struct srvsvc_NetConnInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetConnInfo1 {
+ uint32_t conn_id;
+ uint32_t conn_type;
+ uint32_t num_open;
+ uint32_t num_users;
+ uint32_t conn_time;
+ const char *user;/* [unique,charset(UTF16)] */
+ const char *share;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetConnCtr1 {
+ uint32_t count;
+ struct srvsvc_NetConnInfo1 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetConnCtr {
+ struct srvsvc_NetConnCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetConnCtr1 *ctr1;/* [unique,case] */
+};
+
+struct srvsvc_NetFileInfo2 {
+ uint32_t fid;
+};
+
+struct srvsvc_NetFileCtr2 {
+ uint32_t count;
+ struct srvsvc_NetFileInfo2 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetFileInfo3 {
+ uint32_t fid;
+ uint32_t permissions;
+ uint32_t num_locks;
+ const char *path;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetFileCtr3 {
+ uint32_t count;
+ struct srvsvc_NetFileInfo3 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetFileInfo {
+ struct srvsvc_NetFileInfo2 *info2;/* [unique,case(2)] */
+ struct srvsvc_NetFileInfo3 *info3;/* [unique,case(3)] */
+};
+
+union srvsvc_NetFileCtr {
+ struct srvsvc_NetFileCtr2 *ctr2;/* [unique,case(2)] */
+ struct srvsvc_NetFileCtr3 *ctr3;/* [unique,case(3)] */
+};
+
+struct srvsvc_NetSessInfo0 {
+ const char *client;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSessCtr0 {
+ uint32_t count;
+ struct srvsvc_NetSessInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetSessInfo1 {
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t num_open;
+ uint32_t time;
+ uint32_t idle_time;
+ uint32_t user_flags;
+};
+
+struct srvsvc_NetSessCtr1 {
+ uint32_t count;
+ struct srvsvc_NetSessInfo1 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetSessInfo2 {
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t num_open;
+ uint32_t time;
+ uint32_t idle_time;
+ uint32_t user_flags;
+ const char *client_type;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSessCtr2 {
+ uint32_t count;
+ struct srvsvc_NetSessInfo2 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetSessInfo10 {
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t time;
+ uint32_t idle_time;
+};
+
+struct srvsvc_NetSessCtr10 {
+ uint32_t count;
+ struct srvsvc_NetSessInfo10 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetSessInfo502 {
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t num_open;
+ uint32_t time;
+ uint32_t idle_time;
+ uint32_t user_flags;
+ const char *client_type;/* [unique,charset(UTF16)] */
+ const char *transport;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSessCtr502 {
+ uint32_t count;
+ struct srvsvc_NetSessInfo502 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetSessCtr {
+ struct srvsvc_NetSessCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetSessCtr1 *ctr1;/* [unique,case] */
+ struct srvsvc_NetSessCtr2 *ctr2;/* [unique,case(2)] */
+ struct srvsvc_NetSessCtr10 *ctr10;/* [unique,case(10)] */
+ struct srvsvc_NetSessCtr502 *ctr502;/* [unique,case(502)] */
+};
+
+enum srvsvc_ShareType {
+ STYPE_DISKTREE=0,
+ STYPE_DISKTREE_TEMPORARY=STYPE_DISKTREE|STYPE_TEMPORARY,
+ STYPE_DISKTREE_HIDDEN=STYPE_DISKTREE|STYPE_HIDDEN,
+ STYPE_PRINTQ=1,
+ STYPE_PRINTQ_TEMPORARY=STYPE_PRINTQ|STYPE_TEMPORARY,
+ STYPE_PRINTQ_HIDDEN=STYPE_PRINTQ|STYPE_HIDDEN,
+ STYPE_DEVICE=2,
+ STYPE_DEVICE_TEMPORARY=STYPE_DEVICE|STYPE_TEMPORARY,
+ STYPE_DEVICE_HIDDEN=STYPE_DEVICE|STYPE_HIDDEN,
+ STYPE_IPC=3,
+ STYPE_IPC_TEMPORARY=STYPE_IPC|STYPE_TEMPORARY,
+ STYPE_IPC_HIDDEN=STYPE_IPC|STYPE_HIDDEN
+};
+
+struct srvsvc_NetShareInfo0 {
+ const char *name;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetShareCtr0 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo1 {
+ const char *name;/* [unique,charset(UTF16)] */
+ enum srvsvc_ShareType type;
+ const char *comment;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetShareCtr1 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo1 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo2 {
+ const char *name;/* [unique,charset(UTF16)] */
+ enum srvsvc_ShareType type;
+ const char *comment;/* [unique,charset(UTF16)] */
+ uint32_t permissions;
+ uint32_t max_users;
+ uint32_t current_users;
+ const char *path;/* [unique,charset(UTF16)] */
+ const char *password;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetShareCtr2 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo2 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo501 {
+ const char *name;/* [unique,charset(UTF16)] */
+ enum srvsvc_ShareType type;
+ const char *comment;/* [unique,charset(UTF16)] */
+ uint32_t csc_policy;
+};
+
+struct srvsvc_NetShareCtr501 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo501 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo502 {
+ const char *name;/* [unique,charset(UTF16)] */
+ enum srvsvc_ShareType type;
+ const char *comment;/* [unique,charset(UTF16)] */
+ uint32_t permissions;
+ int32_t max_users;
+ uint32_t current_users;
+ const char *path;/* [unique,charset(UTF16)] */
+ const char *password;/* [unique,charset(UTF16)] */
+ uint32_t unknown;
+ struct security_descriptor *sd;/* [unique,subcontext(4)] */
+};
+
+struct srvsvc_NetShareCtr502 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo502 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo1004 {
+ const char *comment;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetShareCtr1004 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo1004 *array;/* [unique,size_is(count)] */
+};
+
+/* bitmap NetShareInfo1005Flags */
+#define SHARE_1005_IN_DFS ( 0x00000001 )
+#define SHARE_1005_DFS_ROOT ( 0x00000002 )
+
+struct srvsvc_NetShareInfo1005 {
+ uint32_t dfs_flags;
+};
+
+struct srvsvc_NetShareCtr1005 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo1005 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo1006 {
+ int32_t max_users;
+};
+
+struct srvsvc_NetShareCtr1006 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo1006 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareInfo1007 {
+ uint32_t flags;
+ const char *alternate_directory_name;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetShareCtr1007 {
+ uint32_t count;
+ struct srvsvc_NetShareInfo1007 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetShareCtr1501 {
+ uint32_t count;
+ struct sec_desc_buf *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetShareInfo {
+ struct srvsvc_NetShareInfo0 *info0;/* [unique,case(0)] */
+ struct srvsvc_NetShareInfo1 *info1;/* [unique,case] */
+ struct srvsvc_NetShareInfo2 *info2;/* [unique,case(2)] */
+ struct srvsvc_NetShareInfo501 *info501;/* [unique,case(501)] */
+ struct srvsvc_NetShareInfo502 *info502;/* [unique,case(502)] */
+ struct srvsvc_NetShareInfo1004 *info1004;/* [unique,case(1004)] */
+ struct srvsvc_NetShareInfo1005 *info1005;/* [unique,case(1005)] */
+ struct srvsvc_NetShareInfo1006 *info1006;/* [unique,case(1006)] */
+ struct srvsvc_NetShareInfo1007 *info1007;/* [unique,case(1007)] */
+ struct sec_desc_buf *info1501;/* [unique,case(1501)] */
+};
+
+union srvsvc_NetShareCtr {
+ struct srvsvc_NetShareCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetShareCtr1 *ctr1;/* [unique,case] */
+ struct srvsvc_NetShareCtr2 *ctr2;/* [unique,case(2)] */
+ struct srvsvc_NetShareCtr501 *ctr501;/* [unique,case(501)] */
+ struct srvsvc_NetShareCtr502 *ctr502;/* [unique,case(502)] */
+ struct srvsvc_NetShareCtr1004 *ctr1004;/* [unique,case(1004)] */
+ struct srvsvc_NetShareCtr1005 *ctr1005;/* [unique,case(1005)] */
+ struct srvsvc_NetShareCtr1006 *ctr1006;/* [unique,case(1006)] */
+ struct srvsvc_NetShareCtr1007 *ctr1007;/* [unique,case(1007)] */
+ struct srvsvc_NetShareCtr1501 *ctr1501;/* [unique,case(1501)] */
+};
+
+enum srvsvc_PlatformId {
+ PLATFORM_ID_DOS=300,
+ PLATFORM_ID_OS2=400,
+ PLATFORM_ID_NT=500,
+ PLATFORM_ID_OSF=600,
+ PLATFORM_ID_VMS=700
+};
+
+struct srvsvc_NetSrvInfo100 {
+ enum srvsvc_PlatformId platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo101 {
+ enum srvsvc_PlatformId platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t server_type;
+ const char *comment;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo102 {
+ enum srvsvc_PlatformId platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t server_type;
+ const char *comment;/* [unique,charset(UTF16)] */
+ uint32_t users;
+ uint32_t disc;
+ uint32_t hidden;
+ uint32_t announce;
+ uint32_t anndelta;
+ uint32_t licenses;
+ const char *userpath;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo402 {
+ uint32_t ulist_mtime;
+ uint32_t glist_mtime;
+ uint32_t alist_mtime;
+ const char *alerts;/* [unique,charset(UTF16)] */
+ uint32_t security;
+ uint32_t numadmin;
+ uint32_t lanmask;
+ const char *guestaccount;/* [unique,charset(UTF16)] */
+ uint32_t chdevs;
+ uint32_t chdevqs;
+ uint32_t chdevjobs;
+ uint32_t connections;
+ uint32_t shares;
+ uint32_t openfiles;
+ uint32_t sessopen;
+ uint32_t sesssvc;
+ uint32_t sessreqs;
+ uint32_t opensearch;
+ uint32_t activelocks;
+ uint32_t sizereqbufs;
+ uint32_t numbigbufs;
+ uint32_t numfiletasks;
+ uint32_t alertsched;
+ uint32_t erroralert;
+ uint32_t logonalert;
+ uint32_t accessalert;
+ uint32_t diskalert;
+ uint32_t netioalert;
+ uint32_t maxaudits;
+ const char *srvheuristics;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo403 {
+ uint32_t ulist_mtime;
+ uint32_t glist_mtime;
+ uint32_t alist_mtime;
+ const char *alerts;/* [unique,charset(UTF16)] */
+ uint32_t security;
+ uint32_t numadmin;
+ uint32_t lanmask;
+ const char *guestaccount;/* [unique,charset(UTF16)] */
+ uint32_t chdevs;
+ uint32_t chdevqs;
+ uint32_t chdevjobs;
+ uint32_t connections;
+ uint32_t shares;
+ uint32_t openfiles;
+ uint32_t sessopen;
+ uint32_t sesssvc;
+ uint32_t sessreqs;
+ uint32_t opensearch;
+ uint32_t activelocks;
+ uint32_t sizereqbufs;
+ uint32_t numbigbufs;
+ uint32_t numfiletasks;
+ uint32_t alertsched;
+ uint32_t eroralert;
+ uint32_t logonalert;
+ uint32_t accessalert;
+ uint32_t diskalert;
+ uint32_t netioalert;
+ uint32_t maxaudits;
+ const char *srvheuristics;/* [unique,charset(UTF16)] */
+ uint32_t auditedevents;
+ uint32_t auditprofile;
+ const char *autopath;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo502 {
+ uint32_t sessopen;
+ uint32_t sesssvc;
+ uint32_t opensearch;
+ uint32_t sizereqbufs;
+ uint32_t initworkitems;
+ uint32_t maxworkitems;
+ uint32_t rawworkitems;
+ uint32_t irpstacksize;
+ uint32_t maxrawbuflen;
+ uint32_t sessusers;
+ uint32_t sessconns;
+ uint32_t maxpagedmemoryusage;
+ uint32_t maxnonpagedmemoryusage;
+ uint32_t enablesoftcompat;
+ uint32_t enableforcedlogoff;
+ uint32_t timesource;
+ uint32_t acceptdownlevelapis;
+ uint32_t lmannounce;
+};
+
+struct srvsvc_NetSrvInfo503 {
+ uint32_t sessopen;
+ uint32_t sesssvc;
+ uint32_t opensearch;
+ uint32_t sizereqbufs;
+ uint32_t initworkitems;
+ uint32_t maxworkitems;
+ uint32_t rawworkitems;
+ uint32_t irpstacksize;
+ uint32_t maxrawbuflen;
+ uint32_t sessusers;
+ uint32_t sessconns;
+ uint32_t maxpagedmemoryusage;
+ uint32_t maxnonpagedmemoryusage;
+ uint32_t enablesoftcompat;
+ uint32_t enableforcedlogoff;
+ uint32_t timesource;
+ uint32_t acceptdownlevelapis;
+ uint32_t lmannounce;
+ const char *domain;/* [unique,charset(UTF16)] */
+ uint32_t maxcopyreadlen;
+ uint32_t maxcopywritelen;
+ uint32_t minkeepsearch;
+ uint32_t maxkeepsearch;
+ uint32_t minkeepcomplsearch;
+ uint32_t maxkeepcomplsearch;
+ uint32_t threadcountadd;
+ uint32_t numlockthreads;
+ uint32_t scavtimeout;
+ uint32_t minrcvqueue;
+ uint32_t minfreeworkitems;
+ uint32_t xactmemsize;
+ uint32_t threadpriority;
+ uint32_t maxmpxct;
+ uint32_t oplockbreakwait;
+ uint32_t oplockbreakresponsewait;
+ uint32_t enableoplocks;
+ uint32_t enableoplockforceclose;
+ uint32_t enablefcbopens;
+ uint32_t enableraw;
+ uint32_t enablesharednetdrives;
+ uint32_t minfreeconnections;
+ uint32_t maxfreeconnections;
+};
+
+struct srvsvc_NetSrvInfo599 {
+ uint32_t sessopen;
+ uint32_t sesssvc;
+ uint32_t opensearch;
+ uint32_t sizereqbufs;
+ uint32_t initworkitems;
+ uint32_t maxworkitems;
+ uint32_t rawworkitems;
+ uint32_t irpstacksize;
+ uint32_t maxrawbuflen;
+ uint32_t sessusers;
+ uint32_t sessconns;
+ uint32_t maxpagedmemoryusage;
+ uint32_t maxnonpagedmemoryusage;
+ uint32_t enablesoftcompat;
+ uint32_t enableforcedlogoff;
+ uint32_t timesource;
+ uint32_t acceptdownlevelapis;
+ uint32_t lmannounce;
+ const char *domain;/* [unique,charset(UTF16)] */
+ uint32_t maxcopyreadlen;
+ uint32_t maxcopywritelen;
+ uint32_t minkeepsearch;
+ uint32_t minkeepcomplsearch;
+ uint32_t maxkeepcomplsearch;
+ uint32_t threadcountadd;
+ uint32_t numlockthreads;
+ uint32_t scavtimeout;
+ uint32_t minrcvqueue;
+ uint32_t minfreeworkitems;
+ uint32_t xactmemsize;
+ uint32_t threadpriority;
+ uint32_t maxmpxct;
+ uint32_t oplockbreakwait;
+ uint32_t oplockbreakresponsewait;
+ uint32_t enableoplocks;
+ uint32_t enableoplockforceclose;
+ uint32_t enablefcbopens;
+ uint32_t enableraw;
+ uint32_t enablesharednetdrives;
+ uint32_t minfreeconnections;
+ uint32_t maxfreeconnections;
+ uint32_t initsesstable;
+ uint32_t initconntable;
+ uint32_t initfiletable;
+ uint32_t initsearchtable;
+ uint32_t alertsched;
+ uint32_t errortreshold;
+ uint32_t networkerrortreshold;
+ uint32_t diskspacetreshold;
+ uint32_t reserved;
+ uint32_t maxlinkdelay;
+ uint32_t minlinkthroughput;
+ uint32_t linkinfovalidtime;
+ uint32_t scavqosinfoupdatetime;
+ uint32_t maxworkitemidletime;
+};
+
+struct srvsvc_NetSrvInfo1005 {
+ const char *comment;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetSrvInfo1010 {
+ uint32_t disc;
+};
+
+struct srvsvc_NetSrvInfo1016 {
+ uint32_t hidden;
+};
+
+struct srvsvc_NetSrvInfo1017 {
+ uint32_t announce;
+};
+
+struct srvsvc_NetSrvInfo1018 {
+ uint32_t anndelta;
+};
+
+struct srvsvc_NetSrvInfo1107 {
+ uint32_t users;
+};
+
+struct srvsvc_NetSrvInfo1501 {
+ uint32_t sessopens;
+};
+
+struct srvsvc_NetSrvInfo1502 {
+ uint32_t sessvcs;
+};
+
+struct srvsvc_NetSrvInfo1503 {
+ uint32_t opensearch;
+};
+
+struct srvsvc_NetSrvInfo1506 {
+ uint32_t maxworkitems;
+};
+
+struct srvsvc_NetSrvInfo1509 {
+ uint32_t maxrawbuflen;
+};
+
+struct srvsvc_NetSrvInfo1510 {
+ uint32_t sessusers;
+};
+
+struct srvsvc_NetSrvInfo1511 {
+ uint32_t sesscons;
+};
+
+struct srvsvc_NetSrvInfo1512 {
+ uint32_t maxnonpagedmemoryusage;
+};
+
+struct srvsvc_NetSrvInfo1513 {
+ uint32_t maxpagedmemoryusage;
+};
+
+struct srvsvc_NetSrvInfo1514 {
+ uint32_t enablesoftcompat;
+};
+
+struct srvsvc_NetSrvInfo1515 {
+ uint32_t enableforcedlogoff;
+};
+
+struct srvsvc_NetSrvInfo1516 {
+ uint32_t timesource;
+};
+
+struct srvsvc_NetSrvInfo1518 {
+ uint32_t lmannounce;
+};
+
+struct srvsvc_NetSrvInfo1520 {
+ uint32_t maxcopyreadlen;
+};
+
+struct srvsvc_NetSrvInfo1521 {
+ uint32_t maxcopywritelen;
+};
+
+struct srvsvc_NetSrvInfo1522 {
+ uint32_t minkeepsearch;
+};
+
+struct srvsvc_NetSrvInfo1523 {
+ uint32_t maxkeepsearch;
+};
+
+struct srvsvc_NetSrvInfo1524 {
+ uint32_t minkeepcomplsearch;
+};
+
+struct srvsvc_NetSrvInfo1525 {
+ uint32_t maxkeepcomplsearch;
+};
+
+struct srvsvc_NetSrvInfo1528 {
+ uint32_t scavtimeout;
+};
+
+struct srvsvc_NetSrvInfo1529 {
+ uint32_t minrcvqueue;
+};
+
+struct srvsvc_NetSrvInfo1530 {
+ uint32_t minfreeworkitems;
+};
+
+struct srvsvc_NetSrvInfo1533 {
+ uint32_t maxmpxct;
+};
+
+struct srvsvc_NetSrvInfo1534 {
+ uint32_t oplockbreakwait;
+};
+
+struct srvsvc_NetSrvInfo1535 {
+ uint32_t oplockbreakresponsewait;
+};
+
+struct srvsvc_NetSrvInfo1536 {
+ uint32_t enableoplocks;
+};
+
+struct srvsvc_NetSrvInfo1537 {
+ uint32_t enableoplockforceclose;
+};
+
+struct srvsvc_NetSrvInfo1538 {
+ uint32_t enablefcbopens;
+};
+
+struct srvsvc_NetSrvInfo1539 {
+ uint32_t enableraw;
+};
+
+struct srvsvc_NetSrvInfo1540 {
+ uint32_t enablesharednetdrives;
+};
+
+struct srvsvc_NetSrvInfo1541 {
+ uint32_t minfreeconnections;
+};
+
+struct srvsvc_NetSrvInfo1542 {
+ uint32_t maxfreeconnections;
+};
+
+struct srvsvc_NetSrvInfo1543 {
+ uint32_t initsesstable;
+};
+
+struct srvsvc_NetSrvInfo1544 {
+ uint32_t initconntable;
+};
+
+struct srvsvc_NetSrvInfo1545 {
+ uint32_t initfiletable;
+};
+
+struct srvsvc_NetSrvInfo1546 {
+ uint32_t initsearchtable;
+};
+
+struct srvsvc_NetSrvInfo1547 {
+ uint32_t alertsched;
+};
+
+struct srvsvc_NetSrvInfo1548 {
+ uint32_t errortreshold;
+};
+
+struct srvsvc_NetSrvInfo1549 {
+ uint32_t networkerrortreshold;
+};
+
+struct srvsvc_NetSrvInfo1550 {
+ uint32_t diskspacetreshold;
+};
+
+struct srvsvc_NetSrvInfo1552 {
+ uint32_t maxlinkdelay;
+};
+
+struct srvsvc_NetSrvInfo1553 {
+ uint32_t minlinkthroughput;
+};
+
+struct srvsvc_NetSrvInfo1554 {
+ uint32_t linkinfovalidtime;
+};
+
+struct srvsvc_NetSrvInfo1555 {
+ uint32_t scavqosinfoupdatetime;
+};
+
+struct srvsvc_NetSrvInfo1556 {
+ uint32_t maxworkitemidletime;
+};
+
+union srvsvc_NetSrvInfo {
+ struct srvsvc_NetSrvInfo100 *info100;/* [unique,case(100)] */
+ struct srvsvc_NetSrvInfo101 *info101;/* [unique,case(101)] */
+ struct srvsvc_NetSrvInfo102 *info102;/* [unique,case(102)] */
+ struct srvsvc_NetSrvInfo402 *info402;/* [unique,case(402)] */
+ struct srvsvc_NetSrvInfo403 *info403;/* [unique,case(403)] */
+ struct srvsvc_NetSrvInfo502 *info502;/* [unique,case(502)] */
+ struct srvsvc_NetSrvInfo503 *info503;/* [unique,case(503)] */
+ struct srvsvc_NetSrvInfo599 *info599;/* [unique,case(599)] */
+ struct srvsvc_NetSrvInfo1005 *info1005;/* [unique,case(1005)] */
+ struct srvsvc_NetSrvInfo1010 *info1010;/* [unique,case(1010)] */
+ struct srvsvc_NetSrvInfo1016 *info1016;/* [unique,case(1016)] */
+ struct srvsvc_NetSrvInfo1017 *info1017;/* [unique,case(1017)] */
+ struct srvsvc_NetSrvInfo1018 *info1018;/* [unique,case(1018)] */
+ struct srvsvc_NetSrvInfo1107 *info1107;/* [unique,case(1107)] */
+ struct srvsvc_NetSrvInfo1501 *info1501;/* [unique,case(1501)] */
+ struct srvsvc_NetSrvInfo1502 *info1502;/* [unique,case(1502)] */
+ struct srvsvc_NetSrvInfo1503 *info1503;/* [unique,case(1503)] */
+ struct srvsvc_NetSrvInfo1506 *info1506;/* [unique,case(1506)] */
+ struct srvsvc_NetSrvInfo1509 *info1509;/* [unique,case(1509)] */
+ struct srvsvc_NetSrvInfo1510 *info1510;/* [unique,case(1510)] */
+ struct srvsvc_NetSrvInfo1511 *info1511;/* [unique,case(1511)] */
+ struct srvsvc_NetSrvInfo1512 *info1512;/* [unique,case(1512)] */
+ struct srvsvc_NetSrvInfo1513 *info1513;/* [unique,case(1513)] */
+ struct srvsvc_NetSrvInfo1514 *info1514;/* [unique,case(1514)] */
+ struct srvsvc_NetSrvInfo1515 *info1515;/* [unique,case(1515)] */
+ struct srvsvc_NetSrvInfo1516 *info1516;/* [unique,case(1516)] */
+ struct srvsvc_NetSrvInfo1518 *info1518;/* [unique,case(1518)] */
+ struct srvsvc_NetSrvInfo1520 *info1520;/* [unique,case(1520)] */
+ struct srvsvc_NetSrvInfo1521 *info1521;/* [unique,case(1521)] */
+ struct srvsvc_NetSrvInfo1522 *info1522;/* [unique,case(1522)] */
+ struct srvsvc_NetSrvInfo1523 *info1523;/* [unique,case(1523)] */
+ struct srvsvc_NetSrvInfo1524 *info1524;/* [unique,case(1524)] */
+ struct srvsvc_NetSrvInfo1525 *info1525;/* [unique,case(1525)] */
+ struct srvsvc_NetSrvInfo1528 *info1528;/* [unique,case(1528)] */
+ struct srvsvc_NetSrvInfo1529 *info1529;/* [unique,case(1529)] */
+ struct srvsvc_NetSrvInfo1530 *info1530;/* [unique,case(1530)] */
+ struct srvsvc_NetSrvInfo1533 *info1533;/* [unique,case(1533)] */
+ struct srvsvc_NetSrvInfo1534 *info1534;/* [unique,case(1534)] */
+ struct srvsvc_NetSrvInfo1535 *info1535;/* [unique,case(1535)] */
+ struct srvsvc_NetSrvInfo1536 *info1536;/* [unique,case(1536)] */
+ struct srvsvc_NetSrvInfo1537 *info1537;/* [unique,case(1537)] */
+ struct srvsvc_NetSrvInfo1538 *info1538;/* [unique,case(1538)] */
+ struct srvsvc_NetSrvInfo1539 *info1539;/* [unique,case(1539)] */
+ struct srvsvc_NetSrvInfo1540 *info1540;/* [unique,case(1540)] */
+ struct srvsvc_NetSrvInfo1541 *info1541;/* [unique,case(1541)] */
+ struct srvsvc_NetSrvInfo1542 *info1542;/* [unique,case(1542)] */
+ struct srvsvc_NetSrvInfo1543 *info1543;/* [unique,case(1543)] */
+ struct srvsvc_NetSrvInfo1544 *info1544;/* [unique,case(1544)] */
+ struct srvsvc_NetSrvInfo1545 *info1545;/* [unique,case(1545)] */
+ struct srvsvc_NetSrvInfo1546 *info1546;/* [unique,case(1546)] */
+ struct srvsvc_NetSrvInfo1547 *info1547;/* [unique,case(1547)] */
+ struct srvsvc_NetSrvInfo1548 *info1548;/* [unique,case(1548)] */
+ struct srvsvc_NetSrvInfo1549 *info1549;/* [unique,case(1549)] */
+ struct srvsvc_NetSrvInfo1550 *info1550;/* [unique,case(1550)] */
+ struct srvsvc_NetSrvInfo1552 *info1552;/* [unique,case(1552)] */
+ struct srvsvc_NetSrvInfo1553 *info1553;/* [unique,case(1553)] */
+ struct srvsvc_NetSrvInfo1554 *info1554;/* [unique,case(1554)] */
+ struct srvsvc_NetSrvInfo1555 *info1555;/* [unique,case(1555)] */
+ struct srvsvc_NetSrvInfo1556 *info1556;/* [unique,case(1556)] */
+};
+
+struct srvsvc_NetDiskInfo0 {
+ const char * disk;/* [flag(LIBNDR_FLAG_STR_LEN4)] */
+};
+
+struct srvsvc_NetDiskInfo {
+ uint32_t count;
+ struct srvsvc_NetDiskInfo0 *disks;/* [unique,length_is(count),size_is(count)] */
+};
+
+struct srvsvc_Statistics {
+ uint32_t start;
+ uint32_t fopens;
+ uint32_t devopens;
+ uint32_t jobsqueued;
+ uint32_t sopens;
+ uint32_t stimeouts;
+ uint32_t serrorout;
+ uint32_t pwerrors;
+ uint32_t permerrors;
+ uint32_t syserrors;
+ uint32_t bytessent_low;
+ uint32_t bytessent_high;
+ uint32_t bytesrcvd_low;
+ uint32_t bytesrcvd_high;
+ uint32_t avresponse;
+ uint32_t reqbufneed;
+ uint32_t bigbufneed;
+};
+
+struct srvsvc_NetTransportInfo0 {
+ uint32_t vcs;
+ const char *name;/* [unique,charset(UTF16)] */
+ uint8_t *addr;/* [unique,size_is(addr_len)] */
+ uint32_t addr_len;
+ const char *net_addr;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetTransportCtr0 {
+ uint32_t count;
+ struct srvsvc_NetTransportInfo0 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetTransportInfo1 {
+ uint32_t vcs;
+ const char *name;/* [unique,charset(UTF16)] */
+ uint8_t *addr;/* [unique,size_is(addr_len)] */
+ uint32_t addr_len;
+ const char *net_addr;/* [unique,charset(UTF16)] */
+ const char *domain;/* [unique,charset(UTF16)] */
+};
+
+struct srvsvc_NetTransportCtr1 {
+ uint32_t count;
+ struct srvsvc_NetTransportInfo1 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetTransportInfo2 {
+ uint32_t vcs;
+ const char *name;/* [unique,charset(UTF16)] */
+ uint8_t *addr;/* [unique,size_is(addr_len)] */
+ uint32_t addr_len;
+ const char *net_addr;/* [unique,charset(UTF16)] */
+ const char *domain;/* [unique,charset(UTF16)] */
+ uint32_t unknown;
+};
+
+struct srvsvc_NetTransportCtr2 {
+ uint32_t count;
+ struct srvsvc_NetTransportInfo2 *array;/* [unique,size_is(count)] */
+};
+
+struct srvsvc_NetTransportInfo3 {
+ uint32_t vcs;
+ const char *name;/* [unique,charset(UTF16)] */
+ uint8_t *addr;/* [unique,size_is(addr_len)] */
+ uint32_t addr_len;
+ const char *net_addr;/* [unique,charset(UTF16)] */
+ const char *domain;/* [unique,charset(UTF16)] */
+ uint32_t unknown1;
+ uint32_t unknown2;
+ uint8_t unknown3[256];
+};
+
+struct srvsvc_NetTransportCtr3 {
+ uint32_t count;
+ struct srvsvc_NetTransportInfo3 *array;/* [unique,size_is(count)] */
+};
+
+union srvsvc_NetTransportCtr {
+ struct srvsvc_NetTransportCtr0 *ctr0;/* [unique,case(0)] */
+ struct srvsvc_NetTransportCtr1 *ctr1;/* [unique,case] */
+ struct srvsvc_NetTransportCtr2 *ctr2;/* [unique,case(2)] */
+ struct srvsvc_NetTransportCtr3 *ctr3;/* [unique,case(3)] */
+};
+
+struct srvsvc_NetRemoteTODInfo {
+ uint32_t elapsed;
+ uint32_t msecs;
+ uint32_t hours;
+ uint32_t mins;
+ uint32_t secs;
+ uint32_t hunds;
+ int32_t timezone;
+ uint32_t tinterval;
+ uint32_t day;
+ uint32_t month;
+ uint32_t year;
+ uint32_t weekday;
+};
+
+union srvsvc_NetTransportInfo {
+ struct srvsvc_NetTransportInfo0 info0;/* [case(0)] */
+ struct srvsvc_NetTransportInfo1 info1;/* [case] */
+ struct srvsvc_NetTransportInfo2 info2;/* [case(2)] */
+ struct srvsvc_NetTransportInfo3 info3;/* [case(3)] */
+}/* [switch_type(uint32)] */;
+
+
+struct srvsvc_NetCharDevEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetCharDevCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetCharDevCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevGetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *device_name;/* [charset(UTF16)] */
+ uint32_t level;
+ } in;
+
+ struct {
+ union srvsvc_NetCharDevInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevControl {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *device_name;/* [charset(UTF16)] */
+ uint32_t opcode;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevQEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetCharDevQCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetCharDevQCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevQGetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *queue_name;/* [charset(UTF16)] */
+ const char *user;/* [charset(UTF16)] */
+ uint32_t level;
+ } in;
+
+ struct {
+ union srvsvc_NetCharDevQInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevQSetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *queue_name;/* [charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetCharDevQInfo info;/* [switch_is(level)] */
+ uint32_t *parm_error;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *parm_error;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevQPurge {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *queue_name;/* [charset(UTF16)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetCharDevQPurgeSelf {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *queue_name;/* [charset(UTF16)] */
+ const char *computer_name;/* [charset(UTF16)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetConnEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *path;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetConnCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetConnCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetFileEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *path;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetFileCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetFileCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetFileGetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t fid;
+ uint32_t level;
+ } in;
+
+ struct {
+ union srvsvc_NetFileInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetFileClose {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t fid;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSessEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetSessCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetSessCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSessDel {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *client;/* [unique,charset(UTF16)] */
+ const char *user;/* [unique,charset(UTF16)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareAdd {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetShareInfo info;/* [switch_is(level)] */
+ uint32_t *parm_error;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *parm_error;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareEnumAll {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetShareCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetShareCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareGetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share_name;/* [charset(UTF16)] */
+ uint32_t level;
+ } in;
+
+ struct {
+ union srvsvc_NetShareInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareSetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share_name;/* [charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetShareInfo info;/* [switch_is(level)] */
+ uint32_t *parm_error;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *parm_error;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareDel {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share_name;/* [charset(UTF16)] */
+ uint32_t reserved;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareDelSticky {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share_name;/* [charset(UTF16)] */
+ uint32_t reserved;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareCheck {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *device_name;/* [charset(UTF16)] */
+ } in;
+
+ struct {
+ enum srvsvc_ShareType *type;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSrvGetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ } in;
+
+ struct {
+ union srvsvc_NetSrvInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSrvSetInfo {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetSrvInfo info;/* [switch_is(level)] */
+ uint32_t *parm_error;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *parm_error;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetDiskEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ struct srvsvc_NetDiskInfo *info;/* [ref] */
+ uint32_t maxlen;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ struct srvsvc_NetDiskInfo *info;/* [ref] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetServerStatisticsGet {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *service;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ uint32_t options;
+ } in;
+
+ struct {
+ struct srvsvc_Statistics *stats;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetTransportAdd {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetTransportInfo info;/* [switch_is(level)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetTransportEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetTransportCtr *transports;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetTransportCtr *transports;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetTransportDel {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t unknown;
+ struct srvsvc_NetTransportInfo0 transport;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetRemoteTOD {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ } in;
+
+ struct {
+ struct srvsvc_NetRemoteTODInfo *info;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSetServiceBits {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *transport;/* [unique,charset(UTF16)] */
+ uint32_t servicebits;
+ uint32_t updateimmediately;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetPathType {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *path;/* [charset(UTF16)] */
+ uint32_t pathflags;
+ } in;
+
+ struct {
+ uint32_t *pathtype;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetPathCanonicalize {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *path;/* [charset(UTF16)] */
+ uint32_t maxbuf;
+ const char *prefix;/* [charset(UTF16)] */
+ uint32_t *pathtype;/* [ref] */
+ uint32_t pathflags;
+ } in;
+
+ struct {
+ uint8_t *can_path;/* [size_is(maxbuf)] */
+ uint32_t *pathtype;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetPathCompare {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *path1;/* [charset(UTF16)] */
+ const char *path2;/* [charset(UTF16)] */
+ uint32_t pathtype;
+ uint32_t pathflags;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetNameValidate {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *name;/* [charset(UTF16)] */
+ uint32_t name_type;
+ uint32_t flags;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRPRNAMECANONICALIZE {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetPRNameCompare {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *name1;/* [charset(UTF16)] */
+ const char *name2;/* [charset(UTF16)] */
+ uint32_t name_type;
+ uint32_t flags;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareEnum {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetShareCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union srvsvc_NetShareCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareDelStart {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share;/* [charset(UTF16)] */
+ uint32_t reserved;
+ } in;
+
+ struct {
+ struct policy_handle *hnd;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetShareDelCommit {
+ struct {
+ struct policy_handle *hnd;/* [unique] */
+ } in;
+
+ struct {
+ struct policy_handle *hnd;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetGetFileSecurity {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share;/* [unique,charset(UTF16)] */
+ const char *file;/* [charset(UTF16)] */
+ uint32_t securityinformation;
+ } in;
+
+ struct {
+ struct sec_desc_buf *sd_buf;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetSetFileSecurity {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *share;/* [unique,charset(UTF16)] */
+ const char *file;/* [charset(UTF16)] */
+ uint32_t securityinformation;
+ struct sec_desc_buf sd_buf;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetServerTransportAddEx {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union srvsvc_NetTransportInfo info;/* [switch_is(level)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NetServerSetServiceBitsEx {
+ struct {
+ const char *server_unc;/* [unique,charset(UTF16)] */
+ const char *emulated_server_unc;/* [unique,charset(UTF16)] */
+ const char *transport;/* [unique,charset(UTF16)] */
+ uint32_t servicebitsofinterest;
+ uint32_t servicebits;
+ uint32_t updateimmediately;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSGETVERSION {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSCREATELOCALPARTITION {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSDELETELOCALPARTITION {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSSETLOCALVOLUMESTATE {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSSETSERVERINFO {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSCREATEEXITPOINT {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSDELETEEXITPOINT {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSMODIFYPREFIX {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSFIXLOCALVOLUME {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRDFSMANAGERREPORTSITEINFO {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct srvsvc_NETRSERVERTRANSPORTDELEX {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+#endif /* _HEADER_srvsvc */
diff --git a/source/librpc/gen_ndr/svcctl.h b/source/librpc/gen_ndr/svcctl.h
new file mode 100644
index 00000000000..6bc81b93a7d
--- /dev/null
+++ b/source/librpc/gen_ndr/svcctl.h
@@ -0,0 +1,738 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_svcctl
+#define _HEADER_svcctl
+
+#define SERVICE_TYPE_KERNEL_DRIVER ( 0x01 )
+#define SERVICE_TYPE_FS_DRIVER ( 0x02 )
+#define SERVICE_TYPE_ADAPTER ( 0x04 )
+#define SERVICE_TYPE_RECOGNIZER_DRIVER ( 0x08 )
+#define SERVICE_TYPE_DRIVER ( SERVICE_TYPE_KERNEL_DRIVER|SERVICE_TYPE_FS_DRIVER|SERVICE_TYPE_RECOGNIZER_DRIVER )
+#define SERVICE_TYPE_WIN32_OWN_PROCESS ( 0x10 )
+#define SERVICE_TYPE_WIN32_SHARE_PROCESS ( 0x20 )
+#define SERVICE_TYPE_WIN32 ( SERVICE_TYPE_WIN32_OWN_PROCESS|SERVICE_TYPE_WIN32_SHARE_PROCESS )
+#define SERVICE_STATE_ACTIVE ( 0x01 )
+#define SERVICE_STATE_INACTIVE ( 0x02 )
+#define SERVICE_STATE_ALL ( 0x03 )
+#define SV_TYPE_ALL ( 0xFFFFFFFF )
+struct SERVICE_LOCK_STATUS {
+ uint32_t is_locked;
+ const char *lock_owner;/* [unique,charset(UTF16)] */
+ uint32_t lock_duration;
+};
+
+struct SERVICE_STATUS {
+ uint32_t type;
+ uint32_t state;
+ uint32_t controls_accepted;
+ uint32_t win32_exit_code;
+ uint32_t service_exit_code;
+ uint32_t check_point;
+ uint32_t wait_hint;
+};
+
+struct ENUM_SERVICE_STATUS {
+ const char * service_name;/* [relative,flag(LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM)] */
+ const char * display_name;/* [relative,flag(LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM)] */
+ struct SERVICE_STATUS status;
+};
+
+/* bitmap svcctl_ServerType */
+#define SV_TYPE_WORKSTATION ( 0x00000001 )
+#define SV_TYPE_SERVER ( 0x00000002 )
+#define SV_TYPE_SQLSERVER ( 0x00000004 )
+#define SV_TYPE_DOMAIN_CTRL ( 0x00000008 )
+#define SV_TYPE_DOMAIN_BAKCTRL ( 0x00000010 )
+#define SV_TYPE_TIME_SOURCE ( 0x00000020 )
+#define SV_TYPE_AFP ( 0x00000040 )
+#define SV_TYPE_NOVELL ( 0x00000080 )
+#define SV_TYPE_DOMAIN_MEMBER ( 0x00000100 )
+#define SV_TYPE_PRINTQ_SERVER ( 0x00000200 )
+#define SV_TYPE_DIALIN_SERVER ( 0x00000400 )
+#define SV_TYPE_SERVER_UNIX ( 0x00000800 )
+#define SV_TYPE_NT ( 0x00001000 )
+#define SV_TYPE_WFW ( 0x00002000 )
+#define SV_TYPE_SERVER_MFPN ( 0x00004000 )
+#define SV_TYPE_SERVER_NT ( 0x00008000 )
+#define SV_TYPE_POTENTIAL_BROWSER ( 0x00010000 )
+#define SV_TYPE_BACKUP_BROWSER ( 0x00020000 )
+#define SV_TYPE_MASTER_BROWSER ( 0x00040000 )
+#define SV_TYPE_DOMAIN_MASTER ( 0x00080000 )
+#define SV_TYPE_SERVER_OSF ( 0x00100000 )
+#define SV_TYPE_SERVER_VMS ( 0x00200000 )
+#define SV_TYPE_WIN95_PLUS ( 0x00400000 )
+#define SV_TYPE_DFS_SERVER ( 0x00800000 )
+#define SV_TYPE_ALTERNATE_XPORT ( 0x20000000 )
+#define SV_TYPE_LOCAL_LIST_ONLY ( 0x40000000 )
+#define SV_TYPE_DOMAIN_ENUM ( 0x80000000 )
+
+enum SERVICE_CONTROL {
+ FIXME=1
+};
+
+
+struct svcctl_CloseServiceHandle {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ } in;
+
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_ControlService {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t control;
+ } in;
+
+ struct {
+ struct SERVICE_STATUS *status;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_DeleteService {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_LockServiceDatabase {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ } in;
+
+ struct {
+ struct policy_handle *lock;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceObjectSecurity {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_SetServiceObjectSecurity {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceStatus {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ } in;
+
+ struct {
+ struct SERVICE_STATUS *status;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_SetServiceStatus {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_UnlockServiceDatabase {
+ struct {
+ struct policy_handle *lock;/* [ref] */
+ } in;
+
+ struct {
+ struct policy_handle *lock;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_NotifyBootConfigStatus {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_SCSetServiceBitsW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t bits;
+ uint32_t bitson;
+ uint32_t immediate;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_ChangeServiceConfigW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t type;
+ uint32_t start;
+ uint32_t error;
+ const char *binary_path;/* [unique,charset(UTF16)] */
+ const char *load_order_group;/* [unique,charset(UTF16)] */
+ const char *dependencies;/* [unique,charset(UTF16)] */
+ const char *service_start_name;/* [unique,charset(UTF16)] */
+ const char *password;/* [unique,charset(UTF16)] */
+ const char *display_name;/* [unique,charset(UTF16)] */
+ } in;
+
+ struct {
+ uint32_t *tag_id;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_CreateServiceW {
+ struct {
+ struct policy_handle *scmanager_handle;/* [ref] */
+ const char *ServiceName;/* [charset(UTF16)] */
+ const char *DisplayName;/* [unique,charset(UTF16)] */
+ uint32_t desired_access;
+ uint32_t type;
+ uint32_t start_type;
+ uint32_t error_control;
+ const char *binary_path;/* [charset(UTF16)] */
+ const char *LoadOrderGroupKey;/* [unique,charset(UTF16)] */
+ uint32_t *TagId;/* [unique] */
+ uint8_t *dependencies;/* [unique,size_is(dependencies_size)] */
+ uint32_t dependencies_size;
+ const char *service_start_name;/* [unique,charset(UTF16)] */
+ uint8_t *password;/* [unique,size_is(password_size)] */
+ uint32_t password_size;
+ } in;
+
+ struct {
+ uint32_t *TagId;/* [unique] */
+ struct policy_handle *handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_EnumDependentServicesW {
+ struct {
+ struct policy_handle *service;/* [ref] */
+ uint32_t state;
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ struct ENUM_SERVICE_STATUS *status;/* [unique] */
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *services_returned;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_EnumServicesStatusW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t type;
+ uint32_t state;
+ uint32_t buf_size;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint8_t *service;/* [size_is(buf_size)] */
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *services_returned;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_OpenSCManagerW {
+ struct {
+ const char *MachineName;/* [unique,charset(UTF16)] */
+ const char *DatabaseName;/* [unique,charset(UTF16)] */
+ uint32_t access_mask;
+ } in;
+
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_OpenServiceW {
+ struct {
+ struct policy_handle *scmanager_handle;/* [ref] */
+ const char *ServiceName;/* [charset(UTF16)] */
+ uint32_t access_mask;
+ } in;
+
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceConfigW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ uint8_t *query;
+ uint32_t *bytes_needed;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceLockStatusW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ struct SERVICE_LOCK_STATUS *status;/* [ref] */
+ uint32_t *required_buf_size;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_StartServiceW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t NumArgs;
+ const char *Arguments;/* [unique,charset(UTF16),length_is(NumArgs)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_GetServiceDisplayNameW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ const char *service_name;/* [unique,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ } in;
+
+ struct {
+ const char **display_name;/* [ref,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_GetServiceKeyNameW {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ const char *service_name;/* [unique,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ } in;
+
+ struct {
+ const char **key_name;/* [ref,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_SCSetServiceBitsA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t bits;
+ uint32_t bitson;
+ uint32_t immediate;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_ChangeServiceConfigA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t type;
+ uint32_t start;
+ uint32_t error;
+ const char *binary_path;/* [unique,charset(UTF16)] */
+ const char *load_order_group;/* [unique,charset(UTF16)] */
+ const char *dependencies;/* [unique,charset(UTF16)] */
+ const char *service_start_name;/* [unique,charset(UTF16)] */
+ const char *password;/* [unique,charset(UTF16)] */
+ const char *display_name;/* [unique,charset(UTF16)] */
+ } in;
+
+ struct {
+ uint32_t *tag_id;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_CreateServiceA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ const char *ServiceName;/* [unique,charset(UTF16)] */
+ const char *DisplayName;/* [unique,charset(UTF16)] */
+ uint32_t desired_access;
+ uint32_t type;
+ uint32_t start_type;
+ uint32_t error_control;
+ const char *binary_path;/* [unique,charset(UTF16)] */
+ const char *LoadOrderGroupKey;/* [unique,charset(UTF16)] */
+ const char *dependencies;/* [unique,charset(UTF16)] */
+ const char *service_start_name;/* [unique,charset(UTF16)] */
+ const char *password;/* [unique,charset(UTF16)] */
+ } in;
+
+ struct {
+ uint32_t *TagId;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_EnumDependentServicesA {
+ struct {
+ struct policy_handle *service;/* [ref] */
+ uint32_t state;
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ struct ENUM_SERVICE_STATUS *status;/* [unique] */
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *services_returned;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_EnumServicesStatusA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t type;
+ uint32_t state;
+ uint32_t buf_size;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint8_t *service;/* [size_is(buf_size)] */
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *services_returned;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_OpenSCManagerA {
+ struct {
+ const char *MachineName;/* [unique,charset(UTF16)] */
+ const char *DatabaseName;/* [unique,charset(UTF16)] */
+ uint32_t access_mask;
+ } in;
+
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_OpenServiceA {
+ struct {
+ struct policy_handle *scmanager_handle;/* [ref] */
+ const char *ServiceName;/* [unique,charset(UTF16)] */
+ uint32_t access_mask;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceConfigA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ uint8_t *query;
+ uint32_t *bytes_needed;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceLockStatusA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ struct SERVICE_LOCK_STATUS *status;/* [ref] */
+ uint32_t *required_buf_size;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_StartServiceA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t NumArgs;
+ const char *Arguments;/* [unique,charset(UTF16),length_is(NumArgs)] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_GetServiceDisplayNameA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ const char *service_name;/* [unique,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ } in;
+
+ struct {
+ const char **display_name;/* [ref,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_GetServiceKeyNameA {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ const char *service_name;/* [unique,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ } in;
+
+ struct {
+ const char **key_name;/* [ref,charset(UTF16)] */
+ uint32_t *display_name_length;/* [unique] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_GetCurrentGroupeStateW {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_EnumServiceGroupW {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_ChangeServiceConfig2A {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t info_level;
+ uint8_t *info;/* [unique] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_ChangeServiceConfig2W {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t info_level;
+ uint8_t *info;/* [unique] */
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceConfig2A {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t info_level;
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ uint8_t *buffer;
+ uint32_t *bytes_needed;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceConfig2W {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t info_level;
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ uint8_t *buffer;
+ uint32_t *bytes_needed;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_QueryServiceStatusEx {
+ struct {
+ struct policy_handle *handle;/* [ref] */
+ uint32_t info_level;
+ uint32_t buf_size;
+ } in;
+
+ struct {
+ uint8_t *buffer;
+ uint32_t *bytes_needed;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct EnumServicesStatusExA {
+ struct {
+ struct policy_handle *scmanager;/* [ref] */
+ uint32_t info_level;
+ uint32_t type;
+ uint32_t state;
+ uint32_t buf_size;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint8_t *services;
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *service_returned;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ const char **group_name;/* [ref,charset(UTF16)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct EnumServicesStatusExW {
+ struct {
+ struct policy_handle *scmanager;/* [ref] */
+ uint32_t info_level;
+ uint32_t type;
+ uint32_t state;
+ uint32_t buf_size;
+ uint32_t *resume_handle;/* [unique] */
+ } in;
+
+ struct {
+ uint8_t *services;
+ uint32_t *bytes_needed;/* [ref] */
+ uint32_t *service_returned;/* [ref] */
+ uint32_t *resume_handle;/* [unique] */
+ const char **group_name;/* [ref,charset(UTF16)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct svcctl_SCSendTSMessage {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+#endif /* _HEADER_svcctl */
diff --git a/source/librpc/gen_ndr/wkssvc.h b/source/librpc/gen_ndr/wkssvc.h
new file mode 100644
index 00000000000..a6b75920ac5
--- /dev/null
+++ b/source/librpc/gen_ndr/wkssvc.h
@@ -0,0 +1,505 @@
+/* header auto-generated by pidl */
+
+#include "librpc/gen_ndr/srvsvc.h"
+#ifndef _HEADER_wkssvc
+#define _HEADER_wkssvc
+
+struct wkssvc_NetWkstaInfo100 {
+ uint16_t platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *domain_name;/* [unique,charset(UTF16)] */
+ uint32_t version_major;
+ uint32_t version_minor;
+};
+
+struct wkssvc_NetWkstaInfo101 {
+ uint16_t platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *domain_name;/* [unique,charset(UTF16)] */
+ uint32_t version_major;
+ uint32_t version_minor;
+ const char *lan_root;/* [unique,charset(UTF16)] */
+};
+
+struct wkssvc_NetWkstaInfo102 {
+ uint16_t platform_id;
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *domain_name;/* [unique,charset(UTF16)] */
+ uint32_t version_major;
+ uint32_t version_minor;
+ const char *lan_root;/* [unique,charset(UTF16)] */
+ uint32_t logged_on_users;
+};
+
+struct wkssvc_NetWkstaInfo502 {
+ uint32_t char_wait;
+ uint32_t collection_time;
+ uint32_t maximum_collection_count;
+ uint32_t keep_connection;
+ uint32_t max_commands;
+ uint32_t session_timeout;
+ uint32_t size_char_buf;
+ uint32_t max_threads;
+ uint32_t lock_quota;
+ uint32_t lock_increment;
+ uint32_t lock_maximum;
+ uint32_t pipe_increment;
+ uint32_t pipe_maximum;
+ uint32_t cache_file_timeout;
+ uint32_t dormant_file_limit;
+ uint32_t read_ahead_throughput;
+ uint32_t num_mailslot_buffers;
+ uint32_t num_srv_announce_buffers;
+ uint32_t max_illegal_dgram_events;
+ uint32_t dgram_event_reset_freq;
+ uint32_t log_election_packets;
+ uint32_t use_opportunistic_locking;
+ uint32_t use_unlock_behind;
+ uint32_t use_close_behind;
+ uint32_t buf_named_pipes;
+ uint32_t use_lock_read_unlock;
+ uint32_t utilize_nt_caching;
+ uint32_t use_raw_read;
+ uint32_t use_raw_write;
+ uint32_t use_write_raw_data;
+ uint32_t use_encryption;
+ uint32_t buf_files_deny_write;
+ uint32_t buf_read_only_files;
+ uint32_t force_core_create_mode;
+ uint32_t use_512_byte_max_transfer;
+};
+
+struct wkssvc_NetWkstaInfo1010 {
+ uint32_t char_wait;
+};
+
+struct wkssvc_NetWkstaInfo1011 {
+ uint32_t collection_time;
+};
+
+struct wkssvc_NetWkstaInfo1012 {
+ uint32_t maximum_collection_count;
+};
+
+struct wkssvc_NetWkstaInfo1013 {
+ uint32_t keep_connection;
+};
+
+struct wkssvc_NetWkstaInfo1018 {
+ uint32_t session_timeout;
+};
+
+struct wkssvc_NetWkstaInfo1023 {
+ uint32_t size_char_buf;
+};
+
+struct wkssvc_NetWkstaInfo1027 {
+ uint32_t errorlog_sz;
+};
+
+struct wkssvc_NetWkstaInfo1033 {
+ uint32_t max_threads;
+};
+
+union wkssvc_NetWkstaInfo {
+ struct wkssvc_NetWkstaInfo100 *info100;/* [unique,case(100)] */
+ struct wkssvc_NetWkstaInfo101 *info101;/* [unique,case(101)] */
+ struct wkssvc_NetWkstaInfo102 *info102;/* [unique,case(102)] */
+ struct wkssvc_NetWkstaInfo502 *info502;/* [unique,case(502)] */
+ struct wkssvc_NetWkstaInfo1010 *info1010;/* [unique,case(1010)] */
+ struct wkssvc_NetWkstaInfo1011 *info1011;/* [unique,case(1011)] */
+ struct wkssvc_NetWkstaInfo1012 *info1012;/* [unique,case(1012)] */
+ struct wkssvc_NetWkstaInfo1013 *info1013;/* [unique,case(1013)] */
+ struct wkssvc_NetWkstaInfo1018 *info1018;/* [unique,case(1018)] */
+ struct wkssvc_NetWkstaInfo1023 *info1023;/* [unique,case(1023)] */
+ struct wkssvc_NetWkstaInfo1027 *info1027;/* [unique,case(1027)] */
+ struct wkssvc_NetWkstaInfo1033 *info1033;/* [unique,case(1033)] */
+};
+
+struct USER_INFO_0 {
+ const char *user;/* [unique,charset(UTF16)] */
+};
+
+struct USER_INFO_0_CONTAINER {
+ uint32_t entries_read;
+ struct USER_INFO_0 *user0;/* [unique,size_is(entries_read)] */
+};
+
+struct USER_INFO_1 {
+ const char *user_name;/* [unique,charset(UTF16)] */
+ const char *logon_domain;/* [unique,charset(UTF16)] */
+ const char *other_domains;/* [unique,charset(UTF16)] */
+ const char *logon_server;/* [unique,charset(UTF16)] */
+};
+
+struct USER_INFO_1_CONTAINER {
+ uint32_t entries_read;
+ struct USER_INFO_1 *user1;/* [unique,size_is(entries_read)] */
+};
+
+union WKS_USER_ENUM_UNION {
+ struct USER_INFO_0_CONTAINER *user0;/* [unique,case(0)] */
+ struct USER_INFO_1_CONTAINER *user1;/* [unique,case] */
+}/* [switch_type(uint32)] */;
+
+struct wkssvc_NetWkstaTransportInfo0 {
+ uint32_t quality_of_service;
+ uint32_t vc_count;
+ const char *name;/* [unique,charset(UTF16)] */
+ const char *address;/* [unique,charset(UTF16)] */
+ uint32_t wan_link;
+};
+
+struct wkssvc_NetWkstaTransportCtr0 {
+ uint32_t count;
+ struct wkssvc_NetWkstaTransportInfo0 *array;/* [unique,size_is(count)] */
+};
+
+union wkssvc_NetWkstaTransportCtr {
+ struct wkssvc_NetWkstaTransportCtr0 *ctr0;/* [unique,case(0)] */
+};
+
+struct wkssvc_PasswordBuffer {
+ uint8_t data[524];
+};
+
+/* bitmap wkssvc_joinflags */
+#define WKSSVC_JOIN_FLAGS_DEFER_SPN ( 0x00000100 )
+#define WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED ( 0x00000080 )
+#define WKSSVC_JOIN_FLAGS_JOIN_UNSECURE ( 0x00000040 )
+#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define WKSSVC_JOIN_FLAGS_WIN9X_UPGRADE ( 0x00000010 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
+#define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
+
+/* bitmap wkssvc_renameflags */
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
+
+
+struct wkssvc_NetWkstaGetInfo {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ } in;
+
+ struct {
+ union wkssvc_NetWkstaInfo *info;/* [ref,switch_is(level)] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetWkstaSetInfo {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union wkssvc_NetWkstaInfo *info;/* [ref,switch_is(level)] */
+ uint32_t *parm_error;/* [ref] */
+ } in;
+
+ struct {
+ uint32_t *parm_error;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetWkstaEnumUsers {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t level;
+ union WKS_USER_ENUM_UNION *users;/* [ref] */
+ uint32_t prefmaxlen;
+ uint32_t *resumehandle;/* [ref] */
+ } in;
+
+ struct {
+ union WKS_USER_ENUM_UNION *users;/* [ref] */
+ uint32_t *entriesread;/* [unique] */
+ uint32_t *totalentries;/* [unique] */
+ uint32_t *resumehandle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRWKSTAUSERGETINFO {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRWKSTAUSERSETINFO {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetWkstaTransportEnum {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ uint32_t *level;/* [ref] */
+ union wkssvc_NetWkstaTransportCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t max_buffer;
+ uint32_t *resume_handle;/* [ref] */
+ } in;
+
+ struct {
+ uint32_t *level;/* [ref] */
+ union wkssvc_NetWkstaTransportCtr *ctr;/* [ref,switch_is(*level)] */
+ uint32_t *totalentries;/* [unique] */
+ uint32_t *resume_handle;/* [ref] */
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRWKSTATRANSPORTADD {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRWKSTATRANSPORTDEL {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRUSEADD {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRUSEGETINFO {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRUSEDEL {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRUSEENUM {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRMESSAGEBUFFERSEND {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRWORKSTATIONSTATISTICSGET {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRLOGONDOMAINNAMEADD {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRLOGONDOMAINNAMEDEL {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRJOINDOMAIN {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRUNJOINDOMAIN {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRRENAMEMACHINEINDOMAIN {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRVALIDATENAME {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRGETJOININFORMATION {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRGETJOINABLEOUS {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetrJoinDomain2 {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *domain_name;/* [ref,charset(UTF16)] */
+ const char *account_name;/* [unique,charset(UTF16)] */
+ const char *admin_account;/* [unique,charset(UTF16)] */
+ struct wkssvc_PasswordBuffer *encrypted_password;/* [unique] */
+ uint32_t join_flags;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetrUnjoinDomain2 {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *account;/* [unique,charset(UTF16)] */
+ struct wkssvc_PasswordBuffer *encrypted_password;/* [unique] */
+ uint32_t unjoin_flags;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetrRenameMachineInDomain2 {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *NewMachineName;/* [unique,charset(UTF16)] */
+ const char *Account;/* [unique,charset(UTF16)] */
+ struct wkssvc_PasswordBuffer *EncryptedPassword;/* [unique] */
+ uint32_t RenameOptions;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRVALIDATENAME2 {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRGETJOINABLEOUS2 {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetrAddAlternateComputerName {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *NewAlternateMachineName;/* [unique,charset(UTF16)] */
+ const char *Account;/* [unique,charset(UTF16)] */
+ struct wkssvc_PasswordBuffer *EncryptedPassword;/* [unique] */
+ uint32_t Reserved;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct wkssvc_NetrRemoveAlternateComputerName {
+ struct {
+ const char *server_name;/* [unique,charset(UTF16)] */
+ const char *AlternateMachineNameToRemove;/* [unique,charset(UTF16)] */
+ const char *Account;/* [unique,charset(UTF16)] */
+ struct wkssvc_PasswordBuffer *EncryptedPassword;/* [unique] */
+ uint32_t Reserved;
+ } in;
+
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+
+struct WKSSVC_NETRENUMERATECOMPUTERNAMES {
+ struct {
+ WERROR result;
+ } out;
+
+};
+
+#endif /* _HEADER_wkssvc */
diff --git a/source/librpc/ndr/libndr.h b/source/librpc/ndr/libndr.h
new file mode 100644
index 00000000000..32dd0ef6c59
--- /dev/null
+++ b/source/librpc/ndr/libndr.h
@@ -0,0 +1,297 @@
+/*
+ Unix SMB/CIFS implementation.
+ rpc interface definitions
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __LIBNDR_H__
+#define __LIBNDR_H__
+
+#define _PRINTF_ATTRIBUTE(a,b)
+
+#include "librpc/ndr/misc.h"
+#include "librpc/ndr/security.h"
+
+struct dcerpc_syntax_id {
+ struct GUID uuid;
+ uint32_t if_version;
+}/* [public] */;
+
+/*
+ this provides definitions for the libcli/rpc/ MSRPC library
+*/
+
+
+/*
+ this is used by the token store/retrieve code
+*/
+struct ndr_token_list {
+ struct ndr_token_list *next, *prev;
+ const void *key;
+ uint32_t value;
+};
+
+/* this is the base structure passed to routines that
+ parse MSRPC formatted data
+
+ note that in Samba4 we use separate routines and structures for
+ MSRPC marshalling and unmarshalling. Also note that these routines
+ are being kept deliberately very simple, and are not tied to a
+ particular transport
+*/
+struct ndr_pull {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint8_t *data;
+ uint32_t data_size;
+ uint32_t offset;
+
+ uint32_t relative_base_offset;
+ struct ndr_token_list *relative_base_list;
+
+ struct ndr_token_list *relative_list;
+ struct ndr_token_list *array_size_list;
+ struct ndr_token_list *array_length_list;
+ struct ndr_token_list *switch_list;
+
+ TALLOC_CTX *current_mem_ctx;
+
+ /* this is used to ensure we generate unique reference IDs
+ between request and reply */
+ uint32_t ptr_count;
+};
+
+struct ndr_pull_save {
+ uint32_t data_size;
+ uint32_t offset;
+ struct ndr_pull_save *next;
+};
+
+/* structure passed to functions that generate NDR formatted data */
+struct ndr_push {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint8_t *data;
+ uint32_t alloc_size;
+ uint32_t offset;
+
+ uint32_t relative_base_offset;
+ struct ndr_token_list *relative_base_list;
+
+ struct ndr_token_list *switch_list;
+ struct ndr_token_list *relative_list;
+ struct ndr_token_list *nbt_string_list;
+
+ /* this is used to ensure we generate unique reference IDs */
+ uint32_t ptr_count;
+};
+
+struct ndr_push_save {
+ uint32_t offset;
+ struct ndr_push_save *next;
+};
+
+
+/* structure passed to functions that print IDL structures */
+struct ndr_print {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint32_t depth;
+ struct ndr_token_list *switch_list;
+ void (*print)(struct ndr_print *, const char *, ...);
+ void *private_data;
+};
+
+#define LIBNDR_FLAG_BIGENDIAN (1<<0)
+#define LIBNDR_FLAG_NOALIGN (1<<1)
+
+#define LIBNDR_FLAG_STR_ASCII (1<<2)
+#define LIBNDR_FLAG_STR_LEN4 (1<<3)
+#define LIBNDR_FLAG_STR_SIZE4 (1<<4)
+#define LIBNDR_FLAG_STR_NOTERM (1<<5)
+#define LIBNDR_FLAG_STR_NULLTERM (1<<6)
+#define LIBNDR_FLAG_STR_SIZE2 (1<<7)
+#define LIBNDR_FLAG_STR_BYTESIZE (1<<8)
+#define LIBNDR_FLAG_STR_FIXLEN32 (1<<9)
+#define LIBNDR_FLAG_STR_CONFORMANT (1<<10)
+#define LIBNDR_FLAG_STR_CHARLEN (1<<11)
+#define LIBNDR_FLAG_STR_UTF8 (1<<12)
+#define LIBNDR_FLAG_STR_FIXLEN15 (1<<13)
+#define LIBNDR_STRING_FLAGS (0x7FFC)
+
+
+#define LIBNDR_FLAG_REF_ALLOC (1<<20)
+#define LIBNDR_FLAG_REMAINING (1<<21)
+#define LIBNDR_FLAG_ALIGN2 (1<<22)
+#define LIBNDR_FLAG_ALIGN4 (1<<23)
+#define LIBNDR_FLAG_ALIGN8 (1<<24)
+
+#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8)
+
+#define LIBNDR_PRINT_ARRAY_HEX (1<<25)
+#define LIBNDR_PRINT_SET_VALUES (1<<26)
+
+/* used to force a section of IDL to be little-endian */
+#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<27)
+
+/* used to check if alignment padding is zero */
+#define LIBNDR_FLAG_PAD_CHECK (1<<28)
+
+/* set if an object uuid will be present */
+#define LIBNDR_FLAG_OBJECT_PRESENT (1<<30)
+
+/* set to avoid recursion in ndr_size_*() calculation */
+#define LIBNDR_FLAG_NO_NDR_SIZE (1<<31)
+
+/* useful macro for debugging */
+#define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p)
+#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p)
+#define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p)
+#define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p)
+#define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p)
+#define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p)
+
+#define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
+
+enum ndr_err_code {
+ NDR_ERR_ARRAY_SIZE,
+ NDR_ERR_BAD_SWITCH,
+ NDR_ERR_OFFSET,
+ NDR_ERR_RELATIVE,
+ NDR_ERR_CHARCNV,
+ NDR_ERR_LENGTH,
+ NDR_ERR_SUBCONTEXT,
+ NDR_ERR_COMPRESSION,
+ NDR_ERR_STRING,
+ NDR_ERR_VALIDATE,
+ NDR_ERR_BUFSIZE,
+ NDR_ERR_ALLOC,
+ NDR_ERR_RANGE,
+ NDR_ERR_TOKEN,
+ NDR_ERR_IPV4ADDRESS
+};
+
+enum ndr_compression_alg {
+ NDR_COMPRESSION_MSZIP = 2,
+ NDR_COMPRESSION_XPRESS = 3
+};
+
+/*
+ flags passed to control parse flow
+*/
+#define NDR_SCALARS 1
+#define NDR_BUFFERS 2
+
+/*
+ flags passed to ndr_print_*()
+*/
+#define NDR_IN 1
+#define NDR_OUT 2
+#define NDR_BOTH 3
+#define NDR_SET_VALUES 4
+
+#define NDR_PULL_NEED_BYTES(ndr, n) do { \
+ if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u", (unsigned)n); \
+ } \
+} while(0)
+
+#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n)
+
+#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
+
+#define NDR_PULL_ALIGN(ndr, n) do { \
+ if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+ if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \
+ ndr_check_padding(ndr, n); \
+ } \
+ ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
+ } \
+ if (ndr->offset > ndr->data_size) { \
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \
+ } \
+} while(0)
+
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
+
+#define NDR_PUSH_ALIGN(ndr, n) do { \
+ if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+ uint32_t _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \
+ while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); \
+ } \
+} while(0)
+
+/* these are used to make the error checking on each element in libndr
+ less tedious, hopefully making the code more readable */
+#define NDR_CHECK(call) do { NTSTATUS _status; \
+ _status = call; \
+ if (!NT_STATUS_IS_OK(_status)) \
+ return _status; \
+ } while (0)
+
+#define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx)
+
+#define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\
+ if ( !(flgs) || (ndr->flags & flgs) ) {\
+ if (!(mem_ctx)) {\
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "NDR_PULL_SET_MEM_CTX(NULL): %s\n", __location__); \
+ }\
+ ndr->current_mem_ctx = CONST_DISCARD(TALLOC_CTX *, mem_ctx);\
+ }\
+} while(0)
+
+#define _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr) do {\
+ if (!ndr->current_mem_ctx) {\
+ ndr->current_mem_ctx = talloc_new(ndr);\
+ if (!ndr->current_mem_ctx) {\
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "_NDR_PULL_FIX_CURRENT_MEM_CTX() failed: %s\n", __location__); \
+ }\
+ }\
+} while(0)
+
+#define NDR_PULL_ALLOC(ndr, s) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_ptrtype(ndr->current_mem_ctx, (s)); \
+ if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %s failed: %s\n", # s, __location__); \
+} while (0)
+
+#define NDR_PULL_ALLOC_N(ndr, s, n) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_array_ptrtype(ndr->current_mem_ctx, (s), n); \
+ if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %s failed: %s\n", (unsigned)n, # s, __location__); \
+} while (0)
+
+
+#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \
+ (s) = talloc_array(ndr, uint8, size); \
+ if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
+} while (0)
+
+#define NDR_PUSH_ALLOC(ndr, s) do { \
+ (s) = talloc_ptrtype(ndr, (s)); \
+ if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
+} while (0)
+
+/* these are used when generic fn pointers are needed for ndr push/pull fns */
+typedef NTSTATUS (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, const void *);
+typedef NTSTATUS (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *);
+typedef void (*ndr_print_fn_t)(struct ndr_print *, const char *, const void *);
+typedef void (*ndr_print_function_t)(struct ndr_print *, const char *, int, const void *);
+
+extern const struct dcerpc_syntax_id ndr_transfer_syntax;
+extern const struct dcerpc_syntax_id ndr64_transfer_syntax;
+
+#include "dcerpc.h"
+
+#endif /* __LIBNDR_H__ */
diff --git a/source/librpc/ndr/misc.h b/source/librpc/ndr/misc.h
new file mode 100644
index 00000000000..d929379870f
--- /dev/null
+++ b/source/librpc/ndr/misc.h
@@ -0,0 +1,37 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_misc
+#define _HEADER_misc
+
+struct GUID {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq[2];
+ uint8_t node[6];
+}/* [noprint,gensize,public,noejs] */;
+
+struct policy_handle {
+ uint32_t handle_type;
+ struct GUID uuid;
+}/* [public] */;
+
+enum netr_SchannelType {
+ SEC_CHAN_WKSTA=2,
+ SEC_CHAN_DOMAIN=4,
+ SEC_CHAN_BDC=6
+};
+
+enum netr_SamDatabaseID {
+ SAM_DATABASE_DOMAIN=0,
+ SAM_DATABASE_BUILTIN=1,
+ SAM_DATABASE_PRIVS=2
+};
+
+enum samr_RejectReason {
+ SAMR_REJECT_OTHER=0,
+ SAMR_REJECT_TOO_SHORT=1,
+ SAMR_REJECT_COMPLEXITY=2
+};
+
+#endif /* _HEADER_misc */
diff --git a/source/librpc/ndr/ndr.c b/source/librpc/ndr/ndr.c
new file mode 100644
index 00000000000..f6a132c1861
--- /dev/null
+++ b/source/librpc/ndr/ndr.c
@@ -0,0 +1,964 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr interface
+
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ this provides the core routines for NDR parsing functions
+
+ see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
+ of NDR encoding rules
+*/
+
+#include "includes.h"
+
+#define NDR_BASE_MARSHALL_SIZE 1024
+
+/* this guid indicates NDR encoding in a protocol tower */
+const struct dcerpc_syntax_id ndr_transfer_syntax = {
+ { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
+ 2
+};
+
+const struct dcerpc_syntax_id ndr64_transfer_syntax = {
+ { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
+ 1
+};
+
+/*
+ work out the number of bytes needed to align on a n byte boundary
+*/
+size_t ndr_align_size(uint32_t offset, size_t n)
+{
+ if ((offset & (n-1)) == 0) return 0;
+ return n - (offset & (n-1));
+}
+
+/*
+ initialise a ndr parse structure from a data blob
+*/
+struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+ struct ndr_pull *ndr;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ if (!ndr) return NULL;
+ ndr->current_mem_ctx = mem_ctx;
+
+ ndr->data = blob->data;
+ ndr->data_size = blob->length;
+
+ return ndr;
+}
+
+/*
+ advance by 'size' bytes
+*/
+NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
+{
+ ndr->offset += size;
+ if (ndr->offset > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_advance by %u failed",
+ size);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ set the parse offset to 'ofs'
+*/
+static NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
+{
+ ndr->offset = ofs;
+ if (ndr->offset > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_set_offset %u failed",
+ ofs);
+ }
+ return NT_STATUS_OK;
+}
+
+/* save the offset/size of the current ndr state */
+void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save)
+{
+ save->offset = ndr->offset;
+ save->data_size = ndr->data_size;
+}
+
+/* restore the size/offset of a ndr structure */
+void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save)
+{
+ ndr->offset = save->offset;
+ ndr->data_size = save->data_size;
+}
+
+
+/* create a ndr_push structure, ready for some marshalling */
+struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
+{
+ struct ndr_push *ndr;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_push);
+ if (!ndr) {
+ return NULL;
+ }
+
+ ndr->flags = 0;
+ ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
+ ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
+ if (!ndr->data) {
+ return NULL;
+ }
+
+ return ndr;
+}
+
+
+/* create a ndr_push structure, ready for some marshalling */
+struct ndr_push *ndr_push_init(void)
+{
+ return ndr_push_init_ctx(NULL);
+}
+
+/* free a ndr_push structure */
+void ndr_push_free(struct ndr_push *ndr)
+{
+ talloc_free(ndr);
+}
+
+
+/* return a DATA_BLOB structure for the current ndr_push marshalled data */
+DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
+{
+ DATA_BLOB blob;
+ blob.data = ndr->data;
+ blob.length = ndr->offset;
+ blob.free = NULL;
+ if (ndr->alloc_size > ndr->offset) {
+ ndr->data[ndr->offset] = 0;
+ }
+ return blob;
+}
+
+
+/*
+ expand the available space in the buffer to 'size'
+*/
+NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size)
+{
+ if (ndr->alloc_size > size) {
+ return NT_STATUS_OK;
+ }
+
+ ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
+ if (size+1 > ndr->alloc_size) {
+ ndr->alloc_size = size+1;
+ }
+ ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
+ if (!ndr->data) {
+ return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
+ ndr->alloc_size);
+ }
+
+ return NT_STATUS_OK;
+}
+
+void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
+{
+ va_list ap;
+ char *s = NULL;
+ int i;
+
+ va_start(ap, format);
+ vasprintf(&s, format, ap);
+ va_end(ap);
+
+ for (i=0;i<ndr->depth;i++) {
+ DEBUG(0,(" "));
+ }
+
+ DEBUG(0,("%s\n", s));
+ free(s);
+}
+
+static void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
+{
+ va_list ap;
+ int i;
+
+ for (i=0;i<ndr->depth;i++) {
+ ndr->private_data = talloc_asprintf_append(
+ (char *)ndr->private_data, " ");
+ }
+
+ va_start(ap, format);
+ ndr->private_data = talloc_vasprintf_append(
+ (char *)ndr->private_data, format, ap);
+ va_end(ap);
+ ndr->private_data = talloc_asprintf_append(
+ (char *)ndr->private_data, "\n");
+}
+
+/*
+ a useful helper function for printing idl structures via DEBUG()
+*/
+void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ fn(ndr, name, ptr);
+ talloc_free(ndr);
+}
+
+/*
+ a useful helper function for printing idl unions via DEBUG()
+*/
+void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ ndr_print_set_switch_value(ndr, ptr, level);
+ fn(ndr, name, ptr);
+ talloc_free(ndr);
+}
+
+/*
+ a useful helper function for printing idl function calls via DEBUG()
+*/
+void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ fn(ndr, name, flags, ptr);
+ talloc_free(ndr);
+}
+
+
+/*
+ a useful helper function for printing idl function calls to a string
+*/
+char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
+ ndr_print_function_t fn, const char *name,
+ int flags, void *ptr)
+{
+ struct ndr_print *ndr;
+ char *ret = NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_print);
+ if (!ndr) return NULL;
+ if (!(ndr->private_data = talloc_strdup(mem_ctx, ""))) {
+ TALLOC_FREE(ndr);
+ return NULL;
+ }
+ ndr->print = ndr_print_string_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ fn(ndr, name, flags, ptr);
+ ret = (char *)ndr->private_data;
+ talloc_free(ndr);
+ return ret;
+}
+
+void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
+{
+ /* the big/little endian flags are inter-dependent */
+ if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
+ (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
+ }
+ if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
+ (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
+ }
+ if (new_flags & LIBNDR_FLAG_REMAINING) {
+ (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
+ }
+ if (new_flags & LIBNDR_ALIGN_FLAGS) {
+ (*pflags) &= ~LIBNDR_FLAG_REMAINING;
+ }
+ (*pflags) |= new_flags;
+}
+
+static NTSTATUS ndr_map_error(enum ndr_err_code ndr_err)
+{
+ switch (ndr_err) {
+ case NDR_ERR_BUFSIZE:
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ case NDR_ERR_TOKEN:
+ return NT_STATUS_INTERNAL_ERROR;
+ case NDR_ERR_ALLOC:
+ return NT_STATUS_NO_MEMORY;
+ case NDR_ERR_ARRAY_SIZE:
+ return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+ default:
+ break;
+ }
+
+ /* we should map all error codes to different status codes */
+ return NT_STATUS_INVALID_PARAMETER;
+}
+
+/*
+ return and possibly log an NDR error
+*/
+NTSTATUS ndr_pull_error(struct ndr_pull *ndr,
+ enum ndr_err_code ndr_err,
+ const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
+{
+ char *s=NULL;
+ va_list ap;
+
+ va_start(ap, format);
+ vasprintf(&s, format, ap);
+ va_end(ap);
+
+ DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err, s));
+
+ free(s);
+
+ return ndr_map_error(ndr_err);
+}
+
+/*
+ return and possibly log an NDR error
+*/
+NTSTATUS ndr_push_error(struct ndr_push *ndr,
+ enum ndr_err_code ndr_err,
+ const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
+{
+ char *s=NULL;
+ va_list ap;
+
+ va_start(ap, format);
+ vasprintf(&s, format, ap);
+ va_end(ap);
+
+ DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err, s));
+
+ free(s);
+
+ return ndr_map_error(ndr_err);
+}
+
+/*
+ handle subcontext buffers, which in midl land are user-marshalled, but
+ we use magic in pidl to make them easier to cope with
+*/
+NTSTATUS ndr_pull_subcontext_start(struct ndr_pull *ndr,
+ struct ndr_pull **_subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ struct ndr_pull *subndr;
+ uint32_t r_content_size;
+
+ switch (header_size) {
+ case 0: {
+ uint32_t content_size = ndr->data_size - ndr->offset;
+ if (size_is >= 0) {
+ content_size = size_is;
+ }
+ r_content_size = content_size;
+ break;
+ }
+
+ case 2: {
+ uint16_t content_size;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
+ (int)size_is, (int)content_size);
+ }
+ r_content_size = content_size;
+ break;
+ }
+
+ case 4: {
+ uint32_t content_size;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
+ (int)size_is, (int)content_size);
+ }
+ r_content_size = content_size;
+ break;
+ }
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
+ (int)header_size);
+ }
+
+ NDR_PULL_NEED_BYTES(ndr, r_content_size);
+
+ subndr = talloc_zero(ndr, struct ndr_pull);
+ NT_STATUS_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags;
+ subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+ subndr->data = ndr->data + ndr->offset;
+ subndr->offset = 0;
+ subndr->data_size = r_content_size;
+
+ *_subndr = subndr;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_subcontext_end(struct ndr_pull *ndr,
+ struct ndr_pull *subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ uint32_t advance;
+ if (size_is >= 0) {
+ advance = size_is;
+ } else if (header_size > 0) {
+ advance = subndr->data_size;
+ } else {
+ advance = subndr->offset;
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, advance));
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_subcontext_start(struct ndr_push *ndr,
+ struct ndr_push **_subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ struct ndr_push *subndr;
+
+ subndr = ndr_push_init_ctx(ndr);
+ NT_STATUS_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags;
+
+ *_subndr = subndr;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a subcontext header
+*/
+NTSTATUS ndr_push_subcontext_end(struct ndr_push *ndr,
+ struct ndr_push *subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ if (size_is >= 0) {
+ ssize_t padding_len = size_is - subndr->offset;
+ if (padding_len > 0) {
+ NDR_CHECK(ndr_push_zero(subndr, padding_len));
+ } else if (padding_len < 0) {
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
+ (int)subndr->offset, (int)size_is);
+ }
+ }
+
+ switch (header_size) {
+ case 0:
+ break;
+
+ case 2:
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
+ break;
+
+ case 4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
+ (int)header_size);
+ }
+
+ NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
+ return NT_STATUS_OK;
+}
+
+/*
+ store a token in the ndr context, for later retrieval
+*/
+NTSTATUS ndr_token_store(TALLOC_CTX *mem_ctx,
+ struct ndr_token_list **list,
+ const void *key,
+ uint32_t value)
+{
+ struct ndr_token_list *tok;
+ tok = talloc(mem_ctx, struct ndr_token_list);
+ if (tok == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tok->key = key;
+ tok->value = value;
+ DLIST_ADD((*list), tok);
+ return NT_STATUS_OK;
+}
+
+/*
+ retrieve a token from a ndr context, using cmp_fn to match the tokens
+*/
+NTSTATUS ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v,
+ comparison_fn_t _cmp_fn, BOOL _remove_tok)
+{
+ struct ndr_token_list *tok;
+ for (tok=*list;tok;tok=tok->next) {
+ if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found;
+ else if (!_cmp_fn && tok->key == key) goto found;
+ }
+ return ndr_map_error(NDR_ERR_TOKEN);
+found:
+ *v = tok->value;
+ if (_remove_tok) {
+ DLIST_REMOVE((*list), tok);
+ talloc_free(tok);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ retrieve a token from a ndr context
+*/
+NTSTATUS ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v)
+{
+ return ndr_token_retrieve_cmp_fn(list, key, v, NULL, True);
+}
+
+/*
+ peek at but don't removed a token from a ndr context
+*/
+uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
+{
+ NTSTATUS status;
+ uint32_t v;
+ status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, False);
+ if (NT_STATUS_IS_OK(status)) return v;
+ return 0;
+}
+
+/*
+ pull an array size field and add it to the array_size_list token list
+*/
+NTSTATUS ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
+{
+ uint32_t size;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size));
+ return ndr_token_store(ndr, &ndr->array_size_list, p, size);
+}
+
+/*
+ get the stored array size field
+*/
+uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->array_size_list, p);
+}
+
+/*
+ check the stored array size field
+*/
+NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
+{
+ uint32_t stored;
+ stored = ndr_token_peek(&ndr->array_size_list, p);
+ if (stored != size) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size - got %u expected %u\n",
+ stored, size);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ pull an array length field and add it to the array_length_list token list
+*/
+NTSTATUS ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
+{
+ uint32_t length, offset;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &offset));
+ if (offset != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "non-zero array offset %u\n", offset);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+ return ndr_token_store(ndr, &ndr->array_length_list, p, length);
+}
+
+/*
+ get the stored array length field
+*/
+uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->array_length_list, p);
+}
+
+/*
+ check the stored array length field
+*/
+NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
+{
+ uint32_t stored;
+ stored = ndr_token_peek(&ndr->array_length_list, p);
+ if (stored != length) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array length - got %u expected %u\n",
+ stored, length);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ store a switch value
+ */
+NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+/*
+ retrieve a switch value
+ */
+uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+/*
+ pull a struct from a blob using NDR
+*/
+NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+}
+
+/*
+ pull a struct from a blob using NDR - failing if all bytes are not consumed
+*/
+NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ NTSTATUS status;
+
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) return status;
+ if (ndr->offset != ndr->data_size) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+ return status;
+}
+
+/*
+ pull a union from a blob using NDR, given the union discriminator
+*/
+NTSTATUS ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ uint32_t level, ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ NTSTATUS status;
+
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ndr_pull_set_switch_value(ndr, p, level);
+ status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) return status;
+ if (ndr->offset != ndr->data_size) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+ return status;
+}
+
+/*
+ push a struct to a blob using NDR
+*/
+NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p,
+ ndr_push_flags_fn_t fn)
+{
+ NTSTATUS status;
+ struct ndr_push *ndr;
+ ndr = ndr_push_init_ctx(mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *blob = ndr_push_blob(ndr);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ push a union to a blob using NDR
+*/
+NTSTATUS ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ uint32_t level, ndr_push_flags_fn_t fn)
+{
+ NTSTATUS status;
+ struct ndr_push *ndr;
+ ndr = ndr_push_init_ctx(mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ndr_push_set_switch_value(ndr, p, level);
+ status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *blob = ndr_push_blob(ndr);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ generic ndr_size_*() handler for structures
+*/
+size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
+{
+ struct ndr_push *ndr;
+ NTSTATUS status;
+ size_t ret;
+
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+ ndr = ndr_push_init_ctx(NULL);
+ if (!ndr) return 0;
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+ status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return 0;
+ }
+ ret = ndr->offset;
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ generic ndr_size_*() handler for unions
+*/
+size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
+{
+ struct ndr_push *ndr;
+ NTSTATUS status;
+ size_t ret;
+
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+ ndr = ndr_push_init_ctx(NULL);
+ if (!ndr) return 0;
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+ ndr_push_set_switch_value(ndr, p, level);
+ status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return 0;
+ }
+ ret = ndr->offset;
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ get the current base for relative pointers for the push
+*/
+uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
+{
+ return ndr->relative_base_offset;
+}
+
+/*
+ restore the old base for relative pointers for the push
+*/
+void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+}
+
+/*
+ setup the current base for relative pointers for the push
+ called in the NDR_SCALAR stage
+*/
+NTSTATUS ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+ return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+}
+
+/*
+ setup the current base for relative pointers for the push
+ called in the NDR_BUFFERS stage
+*/
+NTSTATUS ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
+{
+ return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+ push a relative object - stage1
+ this is called during SCALARS processing
+*/
+NTSTATUS ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
+{
+ if (p == NULL) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ return NT_STATUS_OK;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset));
+ return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
+}
+
+/*
+ push a relative object - stage2
+ this is called during buffers processing
+*/
+NTSTATUS ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
+{
+ struct ndr_push_save save;
+ uint32_t ptr_offset = 0xFFFFFFFF;
+ if (p == NULL) {
+ return NT_STATUS_OK;
+ }
+ ndr_push_save(ndr, &save);
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
+ if (ptr_offset > ndr->offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
+ ptr_offset, ndr->offset);
+ }
+ ndr->offset = ptr_offset;
+ if (save.offset < ndr->relative_base_offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u)",
+ save.offset, ndr->relative_base_offset);
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save.offset - ndr->relative_base_offset));
+ ndr_push_restore(ndr, &save);
+ return NT_STATUS_OK;
+}
+
+/*
+ get the current base for relative pointers for the pull
+*/
+uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
+{
+ return ndr->relative_base_offset;
+}
+
+/*
+ restore the old base for relative pointers for the pull
+*/
+void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+}
+
+/*
+ setup the current base for relative pointers for the pull
+ called in the NDR_SCALAR stage
+*/
+NTSTATUS ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+ return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+}
+
+/*
+ setup the current base for relative pointers for the pull
+ called in the NDR_BUFFERS stage
+*/
+NTSTATUS ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
+{
+ return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+ pull a relative object - stage1
+ called during SCALARS processing
+*/
+NTSTATUS ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
+{
+ rel_offset += ndr->relative_base_offset;
+ if (rel_offset > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
+ rel_offset, ndr->data_size);
+ }
+ return ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
+}
+
+/*
+ pull a relative object - stage2
+ called during BUFFERS processing
+*/
+NTSTATUS ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
+{
+ uint32_t rel_offset;
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
+ return ndr_pull_set_offset(ndr, rel_offset);
+}
diff --git a/source/librpc/ndr/ndr_basic.c b/source/librpc/ndr/ndr_basic.c
new file mode 100644
index 00000000000..5e75fa1092e
--- /dev/null
+++ b/source/librpc/ndr/ndr_basic.c
@@ -0,0 +1,803 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling basic types
+
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
+#define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
+#define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
+#define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
+#define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
+#define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
+
+
+/*
+ check for data leaks from the server by looking for non-zero pad bytes
+ these could also indicate that real structure elements have been
+ mistaken for padding in the IDL
+*/
+void ndr_check_padding(struct ndr_pull *ndr, size_t n)
+{
+ size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
+ int i;
+ for (i=ndr->offset;i<ofs2;i++) {
+ if (ndr->data[i] != 0) {
+ break;
+ }
+ }
+ if (i<ofs2) {
+ DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
+ for (i=ndr->offset;i<ofs2;i++) {
+ DEBUG(0,("%02x ", ndr->data[i]));
+ }
+ DEBUG(0,("\n"));
+ }
+
+}
+
+/*
+ parse a int8_t
+*/
+NTSTATUS ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
+{
+ NDR_PULL_NEED_BYTES(ndr, 1);
+ *v = (int8_t)CVAL(ndr->data, ndr->offset);
+ ndr->offset += 1;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a uint8_t
+*/
+NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
+{
+ NDR_PULL_NEED_BYTES(ndr, 1);
+ *v = CVAL(ndr->data, ndr->offset);
+ ndr->offset += 1;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a int16_t
+*/
+NTSTATUS ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
+ ndr->offset += 2;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a uint16_t
+*/
+NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ *v = NDR_SVAL(ndr, ndr->offset);
+ ndr->offset += 2;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a int32_t
+*/
+NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 4);
+ *v = NDR_IVALS(ndr, ndr->offset);
+ ndr->offset += 4;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a uint32_t
+*/
+NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 4);
+ *v = NDR_IVAL(ndr, ndr->offset);
+ ndr->offset += 4;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a pointer referent identifier
+*/
+NTSTATUS ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+ NTSTATUS status;
+ status = ndr_pull_uint32(ndr, NDR_SCALARS, v);
+ if (NT_STATUS_IS_OK(status) && *v != 0) {
+ ndr->ptr_count++;
+ }
+ return status;
+}
+
+/*
+ parse a ref pointer referent identifier
+*/
+NTSTATUS ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+ /* ref pointers always point to data */
+ *v = 1;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a udlong
+*/
+NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+ *v = NDR_IVAL(ndr, ndr->offset);
+ *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
+ ndr->offset += 8;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a udlongr
+*/
+NTSTATUS ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+ *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
+ *v |= NDR_IVAL(ndr, ndr->offset+4);
+ ndr->offset += 8;
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a dlong
+*/
+NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
+{
+ return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
+}
+
+/*
+ parse a hyper
+*/
+NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 8);
+ return ndr_pull_udlong(ndr, ndr_flags, v);
+}
+
+/*
+ parse a pointer
+*/
+NTSTATUS ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
+{
+ intptr_t h;
+ NDR_PULL_ALIGN(ndr, sizeof(h));
+ NDR_PULL_NEED_BYTES(ndr, sizeof(h));
+ memcpy(&h, ndr->data+ndr->offset, sizeof(h));
+ ndr->offset += sizeof(h);
+ *v = (void *)h;
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a NTSTATUS
+*/
+NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *status = NT_STATUS(v);
+ return NT_STATUS_OK;
+}
+
+/*
+ push a NTSTATUS
+*/
+NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
+{
+ return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
+}
+
+void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
+{
+ ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
+}
+
+/*
+ pull a WERROR
+*/
+NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *status = W_ERROR(v);
+ return NT_STATUS_OK;
+}
+
+/*
+ push a WERROR
+*/
+NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
+{
+ return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
+}
+
+void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
+{
+ ndr->print(ndr, "%-25s: %s", name, dos_errstr(r));
+}
+
+/*
+ parse a set of bytes
+*/
+NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
+{
+ NDR_PULL_NEED_BYTES(ndr, n);
+ memcpy(data, ndr->data + ndr->offset, n);
+ ndr->offset += n;
+ return NT_STATUS_OK;
+}
+
+/*
+ pull an array of uint8
+*/
+NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+ return ndr_pull_bytes(ndr, data, n);
+}
+
+/*
+ push a int8_t
+*/
+NTSTATUS ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
+{
+ NDR_PUSH_NEED_BYTES(ndr, 1);
+ SCVAL(ndr->data, ndr->offset, (uint8_t)v);
+ ndr->offset += 1;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a uint8_t
+*/
+NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
+{
+ NDR_PUSH_NEED_BYTES(ndr, 1);
+ SCVAL(ndr->data, ndr->offset, v);
+ ndr->offset += 1;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a int16_t
+*/
+NTSTATUS ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 2);
+ NDR_PUSH_NEED_BYTES(ndr, 2);
+ NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
+ ndr->offset += 2;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a uint16_t
+*/
+NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 2);
+ NDR_PUSH_NEED_BYTES(ndr, 2);
+ NDR_SSVAL(ndr, ndr->offset, v);
+ ndr->offset += 2;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a int32_t
+*/
+NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 4);
+ NDR_SIVALS(ndr, ndr->offset, v);
+ ndr->offset += 4;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a uint32_t
+*/
+NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 4);
+ NDR_SIVAL(ndr, ndr->offset, v);
+ ndr->offset += 4;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a udlong
+*/
+NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 8);
+ NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
+ NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
+ ndr->offset += 8;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a udlongr
+*/
+NTSTATUS ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 8);
+ NDR_SIVAL(ndr, ndr->offset, (v>>32));
+ NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
+ ndr->offset += 8;
+ return NT_STATUS_OK;
+}
+
+/*
+ push a dlong
+*/
+NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
+{
+ return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
+}
+
+/*
+ push a hyper
+*/
+NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 8);
+ return ndr_push_udlong(ndr, NDR_SCALARS, v);
+}
+
+/*
+ push a pointer
+*/
+NTSTATUS ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
+{
+ intptr_t h = (intptr_t)v;
+ NDR_PUSH_ALIGN(ndr, sizeof(h));
+ NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
+ memcpy(ndr->data+ndr->offset, &h, sizeof(h));
+ ndr->offset += sizeof(h);
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
+{
+ NDR_PUSH_ALIGN(ndr, size);
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
+{
+ NDR_PULL_ALIGN(ndr, size);
+ return NT_STATUS_OK;
+}
+
+/*
+ push some bytes
+*/
+NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
+{
+ NDR_PUSH_NEED_BYTES(ndr, n);
+ memcpy(ndr->data + ndr->offset, data, n);
+ ndr->offset += n;
+ return NT_STATUS_OK;
+}
+
+/*
+ push some zero bytes
+*/
+NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
+{
+ NDR_PUSH_NEED_BYTES(ndr, n);
+ memset(ndr->data + ndr->offset, 0, n);
+ ndr->offset += n;
+ return NT_STATUS_OK;
+}
+
+/*
+ push an array of uint8
+*/
+NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+ return ndr_push_bytes(ndr, data, n);
+}
+
+/*
+ save the current position
+ */
+void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
+{
+ save->offset = ndr->offset;
+}
+
+/*
+ restore the position
+ */
+void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
+{
+ ndr->offset = save->offset;
+}
+
+/*
+ push a unique non-zero value if a pointer is non-NULL, otherwise 0
+*/
+NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
+{
+ uint32_t ptr = 0;
+ if (p) {
+ ptr = ndr->ptr_count * 4;
+ ptr |= 0x00020000;
+ ndr->ptr_count++;
+ }
+ return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+ push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
+*/
+NTSTATUS ndr_push_sptr_ptr(struct ndr_push *ndr, const void *p)
+{
+ uint32_t ptr = 0;
+ if (p) {
+ ndr->ptr_count++;
+ ptr = ndr->ptr_count;
+ }
+ return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+ push always a 0, if a pointer is NULL it's a fatal error
+*/
+NTSTATUS ndr_push_ref_ptr(struct ndr_push *ndr)
+{
+ return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1);
+}
+
+/*
+ push a NTTIME
+*/
+NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a NTTIME
+*/
+NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ push a NTTIME
+*/
+NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ t /= 10000000;
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a NTTIME_1sec
+*/
+NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
+ (*t) *= 10000000;
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a NTTIME_hyper
+*/
+NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ push a NTTIME_hyper
+*/
+NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ push a time_t
+*/
+NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
+{
+ return ndr_push_uint32(ndr, ndr_flags, t);
+}
+
+/*
+ pull a time_t
+*/
+NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
+{
+ uint32_t tt;
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
+ *t = tt;
+ return NT_STATUS_OK;
+}
+
+
+void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
+{
+ ndr->print(ndr, "%s: struct %s", name, type);
+}
+
+void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type,
+ const char *val, uint32_t value)
+{
+ if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+ ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+ } else {
+ ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+ }
+}
+
+void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
+{
+ /* this is an attempt to support multi-bit bitmap masks */
+ value &= flag;
+
+ while (!(flag & 1)) {
+ flag >>= 1;
+ value >>= 1;
+ }
+ if (flag == 1) {
+ ndr->print(ndr, " %d: %-25s", value, flag_name);
+ } else {
+ ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
+ }
+}
+
+void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
+{
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
+}
+
+void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
+{
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
+}
+
+void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
+{
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
+}
+
+void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, v, v);
+}
+
+void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr_print_udlong(ndr, name, v);
+}
+
+void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, v, v);
+}
+
+void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr_print_dlong(ndr, name, v);
+}
+
+void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
+{
+ ndr->print(ndr, "%-25s: %p", name, v);
+}
+
+void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
+{
+ if (p) {
+ ndr->print(ndr, "%-25s: *", name);
+ } else {
+ ndr->print(ndr, "%-25s: NULL", name);
+ }
+}
+
+void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
+}
+
+void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ /* this is a standard NTTIME here
+ * as it's already converted in the pull/push code
+ */
+ ndr_print_NTTIME(ndr, name, t);
+}
+
+void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ ndr_print_NTTIME(ndr, name, t);
+}
+
+void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
+{
+ if (t == (time_t)-1 || t == 0) {
+ ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
+ } else {
+ ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
+ }
+}
+
+void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
+{
+ if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+ ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
+ } else {
+ ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
+ }
+}
+
+void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
+{
+ ndr->print(ndr, "UNKNOWN LEVEL %u", level);
+}
+
+void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
+ const uint8_t *data, uint32_t count)
+{
+ int i;
+
+ if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+ char s[1202];
+ for (i=0;i<count;i++) {
+ snprintf(&s[i*2], 3, "%02x", data[i]);
+ }
+ s[i*2] = 0;
+ ndr->print(ndr, "%-25s: %s", name, s);
+ return;
+ }
+
+ ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+ ndr->depth++;
+ for (i=0;i<count;i++) {
+ char *idx=NULL;
+ asprintf(&idx, "[%d]", i);
+ if (idx) {
+ ndr_print_uint8(ndr, idx, data[i]);
+ free(idx);
+ }
+ }
+ ndr->depth--;
+}
+
+void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
+{
+ ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
+ if (r.length) {
+ dump_data(10, (const char *)r.data, r.length);
+ }
+}
+
+
+/*
+ push a DATA_BLOB onto the wire.
+*/
+NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
+{
+ if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+ if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ blob.length = NDR_ALIGN(ndr, 2);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ blob.length = NDR_ALIGN(ndr, 4);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ blob.length = NDR_ALIGN(ndr, 8);
+ }
+ NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
+ data_blob_clear(&blob);
+ } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
+ }
+ NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a DATA_BLOB from the wire.
+*/
+NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
+{
+ uint32_t length = 0;
+
+ if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+ if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ length = NDR_ALIGN(ndr, 2);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ length = NDR_ALIGN(ndr, 4);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ length = NDR_ALIGN(ndr, 8);
+ }
+ if (ndr->data_size - ndr->offset < length) {
+ length = ndr->data_size - ndr->offset;
+ }
+ } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ length = ndr->data_size - ndr->offset;
+ } else {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+ }
+ NDR_PULL_NEED_BYTES(ndr, length);
+ *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
+ ndr->offset += length;
+ return NT_STATUS_OK;
+}
+
+uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
+{
+ return ret + data->length;
+}
diff --git a/source/librpc/ndr/ndr_misc.c b/source/librpc/ndr/ndr_misc.c
new file mode 100644
index 00000000000..54face8d7a0
--- /dev/null
+++ b/source/librpc/ndr/ndr_misc.c
@@ -0,0 +1,272 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ UUID/GUID/policy_handle functions
+
+ Copyright (C) Theodore Ts'o 1996, 1997,
+ Copyright (C) Jim McDonough 2002.
+ Copyright (C) Andrew Tridgell 2003.
+ Copyright (C) Stefan (metze) Metzmacher 2004.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+NTSTATUS ndr_push_GUID(struct ndr_push *ndr, int ndr_flags, const struct GUID *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time_low));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->time_mid));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->time_hi_and_version));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->clock_seq, 2));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->node, 6));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, struct GUID *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time_low));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_mid));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->time_hi_and_version));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->clock_seq, 2));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->node, 6));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+size_t ndr_size_GUID(const struct GUID *r, int flags)
+{
+ return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_GUID);
+}
+
+/**
+ build a GUID from a string
+*/
+NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
+{
+ NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+ uint32_t time_low;
+ uint32_t time_mid, time_hi_and_version;
+ uint32_t clock_seq[2];
+ uint32_t node[6];
+ int i;
+
+ if (s == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (11 == sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ &time_low, &time_mid, &time_hi_and_version,
+ &clock_seq[0], &clock_seq[1],
+ &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
+ status = NT_STATUS_OK;
+ } else if (11 == sscanf(s, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ &time_low, &time_mid, &time_hi_and_version,
+ &clock_seq[0], &clock_seq[1],
+ &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
+ status = NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ guid->time_low = time_low;
+ guid->time_mid = time_mid;
+ guid->time_hi_and_version = time_hi_and_version;
+ guid->clock_seq[0] = clock_seq[0];
+ guid->clock_seq[1] = clock_seq[1];
+ for (i=0;i<6;i++) {
+ guid->node[i] = node[i];
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**
+ * generate a random GUID
+ */
+struct GUID GUID_random(void)
+{
+ struct GUID guid;
+
+ generate_random_buffer((uint8_t *)&guid, sizeof(guid));
+ guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80;
+ guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000;
+
+ return guid;
+}
+
+/**
+ * generate an empty GUID
+ */
+struct GUID GUID_zero(void)
+{
+ struct GUID guid;
+
+ ZERO_STRUCT(guid);
+
+ return guid;
+}
+
+/**
+ * see if a range of memory is all zero. A NULL pointer is considered
+ * to be all zero
+ */
+BOOL all_zero(const uint8_t *ptr, size_t size)
+{
+ int i;
+ if (!ptr) return True;
+ for (i=0;i<size;i++) {
+ if (ptr[i]) return False;
+ }
+ return True;
+}
+
+
+BOOL GUID_all_zero(const struct GUID *u)
+{
+ if (u->time_low != 0 ||
+ u->time_mid != 0 ||
+ u->time_hi_and_version != 0 ||
+ u->clock_seq[0] != 0 ||
+ u->clock_seq[1] != 0 ||
+ !all_zero(u->node, 6)) {
+ return False;
+ }
+ return True;
+}
+
+BOOL GUID_equal(const struct GUID *u1, const struct GUID *u2)
+{
+ if (u1->time_low != u2->time_low ||
+ u1->time_mid != u2->time_mid ||
+ u1->time_hi_and_version != u2->time_hi_and_version ||
+ u1->clock_seq[0] != u2->clock_seq[0] ||
+ u1->clock_seq[1] != u2->clock_seq[1] ||
+ memcmp(u1->node, u2->node, 6) != 0) {
+ return False;
+ }
+ return True;
+}
+
+/**
+ its useful to be able to display these in debugging messages
+*/
+char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+ return talloc_asprintf(mem_ctx,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ guid->time_low, guid->time_mid,
+ guid->time_hi_and_version,
+ guid->clock_seq[0],
+ guid->clock_seq[1],
+ guid->node[0], guid->node[1],
+ guid->node[2], guid->node[3],
+ guid->node[4], guid->node[5]);
+}
+
+char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+ char *ret, *s = GUID_string(mem_ctx, guid);
+ ret = talloc_asprintf(mem_ctx, "{%s}", s);
+ talloc_free(s);
+ return ret;
+}
+
+void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
+{
+ ndr->print(ndr, "%-25s: %s", name, GUID_string(ndr, guid));
+}
+
+BOOL policy_handle_empty(struct policy_handle *h)
+{
+ return (h->handle_type == 0 && GUID_all_zero(&h->uuid));
+}
+
+NTSTATUS ndr_push_policy_handle(struct ndr_push *ndr, int ndr_flags, const struct policy_handle *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->handle_type));
+ NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->uuid));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_policy_handle(struct ndr_pull *ndr, int ndr_flags, struct policy_handle *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->handle_type));
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->uuid));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_policy_handle(struct ndr_print *ndr, const char *name, const struct policy_handle *r)
+{
+ ndr_print_struct(ndr, name, "policy_handle");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "handle_type", r->handle_type);
+ ndr_print_GUID(ndr, "uuid", &r->uuid);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_server_id(struct ndr_push *ndr, int ndr_flags, const struct server_id *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS,
+ (uint32_t)r->id.pid));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_server_id(struct ndr_pull *ndr, int ndr_flags, struct server_id *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t pid;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &pid));
+ r->id.pid = (pid_t)pid;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_server_id(struct ndr_print *ndr, const char *name, const struct server_id *r)
+{
+ ndr_print_struct(ndr, name, "server_id");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "id", (uint32_t)r->id.pid);
+ ndr->depth--;
+}
diff --git a/source/librpc/ndr/ndr_sec.h b/source/librpc/ndr/ndr_sec.h
new file mode 100644
index 00000000000..0858eac72c5
--- /dev/null
+++ b/source/librpc/ndr/ndr_sec.h
@@ -0,0 +1,35 @@
+#ifndef __LIBRPC_NDR_NDR_SEC_H__
+#define __LIBRPC_NDR_NDR_SEC_H__
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)
+/* This file was automatically generated by mkproto.pl. DO NOT EDIT */
+
+#ifndef _PUBLIC_
+#define _PUBLIC_
+#endif
+
+
+/* The following definitions come from librpc/ndr/ndr_sec_helper.c */
+
+size_t ndr_size_dom_sid(const struct dom_sid *sid);
+size_t ndr_length_dom_sid(const struct dom_sid *sid);
+size_t ndr_size_security_ace(const struct security_ace *ace);
+size_t ndr_size_security_acl(const struct security_acl *acl);
+size_t ndr_size_security_descriptor(const struct security_descriptor *sd);
+void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid);
+
+/* The following definitions come from librpc/ndr/ndr_sec.c */
+
+NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2)
+
+#endif /* __LIBRPC_NDR_NDR_SEC_H__ */
+
diff --git a/source/librpc/ndr/ndr_sec_helper.c b/source/librpc/ndr/ndr_sec_helper.c
new file mode 100644
index 00000000000..944b172d6cd
--- /dev/null
+++ b/source/librpc/ndr/ndr_sec_helper.c
@@ -0,0 +1,903 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ fast routines for getting the wire size of security objects
+
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "includes.h"
+
+/*
+ return the wire size of a dom_sid
+*/
+size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
+{
+ if (!sid) return 0;
+ return 8 + 4*sid->num_auths;
+}
+
+/*
+ return the wire size of a security_ace
+*/
+size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
+{
+ if (!ace) return 0;
+ return 8 + ndr_size_dom_sid(&ace->trustee, flags);
+}
+
+
+/*
+ return the wire size of a security_acl
+*/
+size_t ndr_size_security_acl(const struct security_acl *acl, int flags)
+{
+ size_t ret;
+ int i;
+ if (!acl) return 0;
+ ret = 8;
+ for (i=0;i<acl->num_aces;i++) {
+ ret += ndr_size_security_ace(&acl->aces[i], flags);
+ }
+ return ret;
+}
+
+/*
+ return the wire size of a security descriptor
+*/
+size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
+{
+ size_t ret;
+ if (!sd) return 0;
+
+ ret = 20;
+ ret += ndr_size_dom_sid(sd->owner_sid, flags);
+ ret += ndr_size_dom_sid(sd->group_sid, flags);
+ ret += ndr_size_security_acl(sd->dacl, flags);
+ ret += ndr_size_security_acl(sd->sacl, flags);
+ return ret;
+}
+
+/*
+ print a dom_sid
+*/
+void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr, sid));
+}
+
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr_print_dom_sid(ndr, name, sid);
+}
+
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr_print_dom_sid(ndr, name, sid);
+}
+
+static NTSTATUS ndr_push_security_ace_flags(struct ndr_push *ndr, int ndr_flags, uint8_t r)
+{
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_flags(struct ndr_pull *ndr, int ndr_flags, uint8_t *r)
+{
+ uint8_t v;
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_flags(struct ndr_print *ndr, const char *name, uint8_t r)
+{
+ ndr_print_uint8(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_OBJECT_INHERIT", SEC_ACE_FLAG_OBJECT_INHERIT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_CONTAINER_INHERIT", SEC_ACE_FLAG_CONTAINER_INHERIT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_NO_PROPAGATE_INHERIT", SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_INHERIT_ONLY", SEC_ACE_FLAG_INHERIT_ONLY, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_INHERITED_ACE", SEC_ACE_FLAG_INHERITED_ACE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_VALID_INHERIT", SEC_ACE_FLAG_VALID_INHERIT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_SUCCESSFUL_ACCESS", SEC_ACE_FLAG_SUCCESSFUL_ACCESS, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint8_t), "SEC_ACE_FLAG_FAILED_ACCESS", SEC_ACE_FLAG_FAILED_ACCESS, r);
+ ndr->depth--;
+}
+
+static NTSTATUS ndr_push_security_ace_type(struct ndr_push *ndr, int ndr_flags, enum security_ace_type r)
+{
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_type(struct ndr_pull *ndr, int ndr_flags, enum security_ace_type *r)
+{
+ uint8_t v;
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_type(struct ndr_print *ndr, const char *name, enum security_ace_type r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED: val = "SEC_ACE_TYPE_ACCESS_ALLOWED"; break;
+ case SEC_ACE_TYPE_ACCESS_DENIED: val = "SEC_ACE_TYPE_ACCESS_DENIED"; break;
+ case SEC_ACE_TYPE_SYSTEM_AUDIT: val = "SEC_ACE_TYPE_SYSTEM_AUDIT"; break;
+ case SEC_ACE_TYPE_SYSTEM_ALARM: val = "SEC_ACE_TYPE_SYSTEM_ALARM"; break;
+ case SEC_ACE_TYPE_ALLOWED_COMPOUND: val = "SEC_ACE_TYPE_ALLOWED_COMPOUND"; break;
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: val = "SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT"; break;
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: val = "SEC_ACE_TYPE_ACCESS_DENIED_OBJECT"; break;
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: val = "SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT"; break;
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: val = "SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+static NTSTATUS ndr_push_security_ace_object_flags(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_object_flags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_object_flags(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_ACE_OBJECT_TYPE_PRESENT", SEC_ACE_OBJECT_TYPE_PRESENT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT", SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT, r);
+ ndr->depth--;
+}
+
+static NTSTATUS ndr_push_security_ace_object_type(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_type *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_OBJECT_TYPE_PRESENT:
+ NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->type));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_OBJECT_TYPE_PRESENT:
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_object_type(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_type *r)
+{
+ int level;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_OBJECT_TYPE_PRESENT: {
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->type));
+ break; }
+
+ default: {
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_OBJECT_TYPE_PRESENT:
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_object_type(struct ndr_print *ndr, const char *name, const union security_ace_object_type *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "security_ace_object_type");
+ switch (level) {
+ case SEC_ACE_OBJECT_TYPE_PRESENT:
+ ndr_print_GUID(ndr, "type", &r->type);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+static NTSTATUS ndr_push_security_ace_object_inherited_type(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_inherited_type *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
+ NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->inherited_type));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_object_inherited_type(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_inherited_type *r)
+{
+ int level;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT: {
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->inherited_type));
+ break; }
+
+ default: {
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_object_inherited_type(struct ndr_print *ndr, const char *name, const union security_ace_object_inherited_type *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "security_ace_object_inherited_type");
+ switch (level) {
+ case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
+ ndr_print_GUID(ndr, "inherited_type", &r->inherited_type);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+static NTSTATUS ndr_push_security_ace_object(struct ndr_push *ndr, int ndr_flags, const struct security_ace_object *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_security_ace_object_flags(ndr, NDR_SCALARS, r->flags));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->type, r->flags&SEC_ACE_OBJECT_TYPE_PRESENT));
+ NDR_CHECK(ndr_push_security_ace_object_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->inherited_type, r->flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT));
+ NDR_CHECK(ndr_push_security_ace_object_inherited_type(ndr, NDR_SCALARS, &r->inherited_type));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_security_ace_object_type(ndr, NDR_BUFFERS, &r->type));
+ NDR_CHECK(ndr_push_security_ace_object_inherited_type(ndr, NDR_BUFFERS, &r->inherited_type));
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_object(struct ndr_pull *ndr, int ndr_flags, struct security_ace_object *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_security_ace_object_flags(ndr, NDR_SCALARS, &r->flags));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->type, r->flags&SEC_ACE_OBJECT_TYPE_PRESENT));
+ NDR_CHECK(ndr_pull_security_ace_object_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->inherited_type, r->flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT));
+ NDR_CHECK(ndr_pull_security_ace_object_inherited_type(ndr, NDR_SCALARS, &r->inherited_type));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_security_ace_object_type(ndr, NDR_BUFFERS, &r->type));
+ NDR_CHECK(ndr_pull_security_ace_object_inherited_type(ndr, NDR_BUFFERS, &r->inherited_type));
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_object(struct ndr_print *ndr, const char *name, const struct security_ace_object *r)
+{
+ ndr_print_struct(ndr, name, "security_ace_object");
+ ndr->depth++;
+ ndr_print_security_ace_object_flags(ndr, "flags", r->flags);
+ ndr_print_set_switch_value(ndr, &r->type, r->flags&SEC_ACE_OBJECT_TYPE_PRESENT);
+ ndr_print_security_ace_object_type(ndr, "type", &r->type);
+ ndr_print_set_switch_value(ndr, &r->inherited_type, r->flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT);
+ ndr_print_security_ace_object_inherited_type(ndr, "inherited_type", &r->inherited_type);
+ ndr->depth--;
+}
+
+static NTSTATUS ndr_push_security_ace_object_ctr(struct ndr_push *ndr, int ndr_flags, const union security_ace_object_ctr *r)
+{
+ int level;
+ level = ndr_push_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ NDR_CHECK(ndr_push_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_ace_object_ctr(struct ndr_pull *ndr, int ndr_flags, union security_ace_object_ctr *r)
+{
+ int level;
+ level = ndr_pull_get_switch_value(ndr, r);
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: {
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break; }
+
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: {
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break; }
+
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: {
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break; }
+
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: {
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_SCALARS, &r->object));
+ break; }
+
+ default: {
+ break; }
+
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ NDR_CHECK(ndr_pull_security_ace_object(ndr, NDR_BUFFERS, &r->object));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace_object_ctr(struct ndr_print *ndr, const char *name, const union security_ace_object_ctr *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "security_ace_object_ctr");
+ switch (level) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ ndr_print_security_ace_object(ndr, "object", &r->object);
+ break;
+
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ ndr_print_security_ace_object(ndr, "object", &r->object);
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ ndr_print_security_ace_object(ndr, "object", &r->object);
+ break;
+
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ ndr_print_security_ace_object(ndr, "object", &r->object);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+NTSTATUS ndr_push_security_ace(struct ndr_push *ndr, int ndr_flags, const struct security_ace *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_security_ace_type(ndr, NDR_SCALARS, r->type));
+ NDR_CHECK(ndr_push_security_ace_flags(ndr, NDR_SCALARS, r->flags));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, ndr_size_security_ace(r,ndr->flags)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->access_mask));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->object, r->type));
+ NDR_CHECK(ndr_push_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, &r->trustee));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object));
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, struct security_ace *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
+ NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object));
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_ace(struct ndr_print *ndr, const char *name, const struct security_ace *r)
+{
+ ndr_print_struct(ndr, name, "security_ace");
+ ndr->depth++;
+ ndr_print_security_ace_type(ndr, "type", r->type);
+ ndr_print_security_ace_flags(ndr, "flags", r->flags);
+ ndr_print_uint16(ndr, "size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_ace(r,ndr->flags):r->size);
+ ndr_print_uint32(ndr, "access_mask", r->access_mask);
+ ndr_print_set_switch_value(ndr, &r->object, r->type);
+ ndr_print_security_ace_object_ctr(ndr, "object", &r->object);
+ ndr_print_dom_sid(ndr, "trustee", &r->trustee);
+ ndr->depth--;
+}
+
+static NTSTATUS ndr_push_security_acl_revision(struct ndr_push *ndr, int ndr_flags, enum security_acl_revision r)
+{
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_acl_revision(struct ndr_pull *ndr, int ndr_flags, enum security_acl_revision *r)
+{
+ uint16_t v;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_acl_revision(struct ndr_print *ndr, const char *name, enum security_acl_revision r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case SECURITY_ACL_REVISION_NT4: val = "SECURITY_ACL_REVISION_NT4"; break;
+ case SECURITY_ACL_REVISION_ADS: val = "SECURITY_ACL_REVISION_ADS"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+NTSTATUS ndr_push_security_acl(struct ndr_push *ndr, int ndr_flags, const struct security_acl *r)
+{
+ uint32_t cntr_aces_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_security_acl_revision(ndr, NDR_SCALARS, r->revision));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, ndr_size_security_acl(r,ndr->flags)));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num_aces));
+ for (cntr_aces_0 = 0; cntr_aces_0 < r->num_aces; cntr_aces_0++) {
+ NDR_CHECK(ndr_push_security_ace(ndr, NDR_SCALARS, &r->aces[cntr_aces_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ for (cntr_aces_0 = 0; cntr_aces_0 < r->num_aces; cntr_aces_0++) {
+ NDR_CHECK(ndr_push_security_ace(ndr, NDR_BUFFERS, &r->aces[cntr_aces_0]));
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_security_acl(struct ndr_pull *ndr, int ndr_flags, struct security_acl *r)
+{
+ uint32_t cntr_aces_0;
+ TALLOC_CTX *_mem_save_aces_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_security_acl_revision(ndr, NDR_SCALARS, &r->revision));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num_aces));
+ if (r->num_aces < 0 || r->num_aces > 1000) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_PULL_ALLOC_N(ndr, r->aces, r->num_aces);
+ _mem_save_aces_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->aces, 0);
+ for (cntr_aces_0 = 0; cntr_aces_0 < r->num_aces; cntr_aces_0++) {
+ NDR_CHECK(ndr_pull_security_ace(ndr, NDR_SCALARS, &r->aces[cntr_aces_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_aces_0, 0);
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ _mem_save_aces_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->aces, 0);
+ for (cntr_aces_0 = 0; cntr_aces_0 < r->num_aces; cntr_aces_0++) {
+ NDR_CHECK(ndr_pull_security_ace(ndr, NDR_BUFFERS, &r->aces[cntr_aces_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_aces_0, 0);
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_acl(struct ndr_print *ndr, const char *name, const struct security_acl *r)
+{
+ uint32_t cntr_aces_0;
+ ndr_print_struct(ndr, name, "security_acl");
+ ndr->depth++;
+ ndr_print_security_acl_revision(ndr, "revision", r->revision);
+ ndr_print_uint16(ndr, "size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_acl(r,ndr->flags):r->size);
+ ndr_print_uint32(ndr, "num_aces", r->num_aces);
+ ndr->print(ndr, "%s: ARRAY(%d)", "aces", r->num_aces);
+ ndr->depth++;
+ for (cntr_aces_0=0;cntr_aces_0<r->num_aces;cntr_aces_0++) {
+ char *idx_0=NULL;
+ asprintf(&idx_0, "[%d]", cntr_aces_0);
+ if (idx_0) {
+ ndr_print_security_ace(ndr, "aces", &r->aces[cntr_aces_0]);
+ free(idx_0);
+ }
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+static NTSTATUS ndr_push_security_descriptor_revision(struct ndr_push *ndr, int ndr_flags, enum security_descriptor_revision r)
+{
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_descriptor_revision(struct ndr_pull *ndr, int ndr_flags, enum security_descriptor_revision *r)
+{
+ uint8_t v;
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_descriptor_revision(struct ndr_print *ndr, const char *name, enum security_descriptor_revision r)
+{
+ const char *val = NULL;
+
+ switch (r) {
+ case SECURITY_DESCRIPTOR_REVISION_1: val = "SECURITY_DESCRIPTOR_REVISION_1"; break;
+ }
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+static NTSTATUS ndr_push_security_descriptor_type(struct ndr_push *ndr, int ndr_flags, uint16_t r)
+{
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ndr_pull_security_descriptor_type(struct ndr_pull *ndr, int ndr_flags, uint16_t *r)
+{
+ uint16_t v;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_descriptor_type(struct ndr_print *ndr, const char *name, uint16_t r)
+{
+ ndr_print_uint16(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_OWNER_DEFAULTED", SEC_DESC_OWNER_DEFAULTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_GROUP_DEFAULTED", SEC_DESC_GROUP_DEFAULTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_PRESENT", SEC_DESC_DACL_PRESENT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_DEFAULTED", SEC_DESC_DACL_DEFAULTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_PRESENT", SEC_DESC_SACL_PRESENT, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_DEFAULTED", SEC_DESC_SACL_DEFAULTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_TRUSTED", SEC_DESC_DACL_TRUSTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SERVER_SECURITY", SEC_DESC_SERVER_SECURITY, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_AUTO_INHERIT_REQ", SEC_DESC_DACL_AUTO_INHERIT_REQ, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_AUTO_INHERIT_REQ", SEC_DESC_SACL_AUTO_INHERIT_REQ, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_AUTO_INHERITED", SEC_DESC_DACL_AUTO_INHERITED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_AUTO_INHERITED", SEC_DESC_SACL_AUTO_INHERITED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_DACL_PROTECTED", SEC_DESC_DACL_PROTECTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SACL_PROTECTED", SEC_DESC_SACL_PROTECTED, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_RM_CONTROL_VALID", SEC_DESC_RM_CONTROL_VALID, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint16_t), "SEC_DESC_SELF_RELATIVE", SEC_DESC_SELF_RELATIVE, r);
+ ndr->depth--;
+}
+
+NTSTATUS ndr_push_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_security_descriptor_revision(ndr, NDR_SCALARS, r->revision));
+ NDR_CHECK(ndr_push_security_descriptor_type(ndr, NDR_SCALARS, r->type));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->owner_sid));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->group_sid));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sacl));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->dacl));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->owner_sid) {
+ NDR_CHECK(ndr_push_relative_ptr2(ndr, r->owner_sid));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->owner_sid));
+ }
+ if (r->group_sid) {
+ NDR_CHECK(ndr_push_relative_ptr2(ndr, r->group_sid));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->group_sid));
+ }
+ if (r->sacl) {
+ NDR_CHECK(ndr_push_relative_ptr2(ndr, r->sacl));
+ NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl));
+ }
+ if (r->dacl) {
+ NDR_CHECK(ndr_push_relative_ptr2(ndr, r->dacl));
+ NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl));
+ }
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_security_descriptor(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor *r)
+{
+ uint32_t _ptr_owner_sid;
+ TALLOC_CTX *_mem_save_owner_sid_0;
+ uint32_t _ptr_group_sid;
+ TALLOC_CTX *_mem_save_group_sid_0;
+ uint32_t _ptr_sacl;
+ TALLOC_CTX *_mem_save_sacl_0;
+ uint32_t _ptr_dacl;
+ TALLOC_CTX *_mem_save_dacl_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_security_descriptor_revision(ndr, NDR_SCALARS, &r->revision));
+ NDR_CHECK(ndr_pull_security_descriptor_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_owner_sid));
+ if (_ptr_owner_sid) {
+ NDR_PULL_ALLOC(ndr, r->owner_sid);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->owner_sid, _ptr_owner_sid));
+ } else {
+ r->owner_sid = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_group_sid));
+ if (_ptr_group_sid) {
+ NDR_PULL_ALLOC(ndr, r->group_sid);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->group_sid, _ptr_group_sid));
+ } else {
+ r->group_sid = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sacl));
+ if (_ptr_sacl) {
+ NDR_PULL_ALLOC(ndr, r->sacl);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->sacl, _ptr_sacl));
+ } else {
+ r->sacl = NULL;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_dacl));
+ if (_ptr_dacl) {
+ NDR_PULL_ALLOC(ndr, r->dacl);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->dacl, _ptr_dacl));
+ } else {
+ r->dacl = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->owner_sid) {
+ struct ndr_pull_save _relative_save;
+ ndr_pull_save(ndr, &_relative_save);
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->owner_sid));
+ _mem_save_owner_sid_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->owner_sid, 0);
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, r->owner_sid));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_owner_sid_0, 0);
+ ndr_pull_restore(ndr, &_relative_save);
+ }
+ if (r->group_sid) {
+ struct ndr_pull_save _relative_save;
+ ndr_pull_save(ndr, &_relative_save);
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->group_sid));
+ _mem_save_group_sid_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->group_sid, 0);
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, r->group_sid));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_group_sid_0, 0);
+ ndr_pull_restore(ndr, &_relative_save);
+ }
+ if (r->sacl) {
+ struct ndr_pull_save _relative_save;
+ ndr_pull_save(ndr, &_relative_save);
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->sacl));
+ _mem_save_sacl_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->sacl, 0);
+ NDR_CHECK(ndr_pull_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sacl_0, 0);
+ ndr_pull_restore(ndr, &_relative_save);
+ }
+ if (r->dacl) {
+ struct ndr_pull_save _relative_save;
+ ndr_pull_save(ndr, &_relative_save);
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->dacl));
+ _mem_save_dacl_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->dacl, 0);
+ NDR_CHECK(ndr_pull_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_dacl_0, 0);
+ ndr_pull_restore(ndr, &_relative_save);
+ }
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_descriptor(struct ndr_print *ndr, const char *name, const struct security_descriptor *r)
+{
+ ndr_print_struct(ndr, name, "security_descriptor");
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
+ ndr->depth++;
+ ndr_print_security_descriptor_revision(ndr, "revision", r->revision);
+ ndr_print_security_descriptor_type(ndr, "type", r->type);
+ ndr_print_ptr(ndr, "owner_sid", r->owner_sid);
+ ndr->depth++;
+ if (r->owner_sid) {
+ ndr_print_dom_sid(ndr, "owner_sid", r->owner_sid);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "group_sid", r->group_sid);
+ ndr->depth++;
+ if (r->group_sid) {
+ ndr_print_dom_sid(ndr, "group_sid", r->group_sid);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "sacl", r->sacl);
+ ndr->depth++;
+ if (r->sacl) {
+ ndr_print_security_acl(ndr, "sacl", r->sacl);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "dacl", r->dacl);
+ ndr->depth++;
+ if (r->dacl) {
+ ndr_print_security_acl(ndr, "dacl", r->dacl);
+ }
+ ndr->depth--;
+ ndr->depth--;
+ ndr->flags = _flags_save_STRUCT;
+ }
+}
+
+NTSTATUS ndr_push_security_secinfo(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_security_secinfo(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+ uint32_t v;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NT_STATUS_OK;
+}
+
+void ndr_print_security_secinfo(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_OWNER", SECINFO_OWNER, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_GROUP", SECINFO_GROUP, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_DACL", SECINFO_DACL, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SECINFO_SACL", SECINFO_SACL, r);
+ ndr->depth--;
+}
+
diff --git a/source/librpc/ndr/ndr_string.c b/source/librpc/ndr/ndr_string.c
new file mode 100644
index 00000000000..2aa86de0bbb
--- /dev/null
+++ b/source/librpc/ndr/ndr_string.c
@@ -0,0 +1,620 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling string types
+
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/**
+ pull a general string from the wire
+*/
+NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
+{
+ char *as=NULL;
+ uint32_t len1, ofs, len2;
+ uint16_t len3;
+ int ret;
+ charset_t chset = CH_UTF16LE;
+ unsigned byte_mul = 2;
+ unsigned flags = ndr->flags;
+ unsigned c_len_term = 0;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ if (NDR_BE(ndr)) {
+ chset = CH_UTF16BE;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_ASCII) {
+ chset = CH_DOS;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_ASCII;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_UTF8) {
+ chset = CH_UTF8;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_UTF8;
+ }
+
+ flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+ if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+ c_len_term = 1;
+ flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+ }
+
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+ if (ofs != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
+ if (len2 > len1) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "Bad string lengths len1=%u ofs=%u len2=%u\n",
+ len1, ofs, len2);
+ }
+ NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
+ if (len2 == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ } else {
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ (len2 + c_len_term)*byte_mul,
+ &as, True);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
+
+ if (len1 != len2) {
+ DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
+ }
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (strlen(as) < (len2 + c_len_term)) {
+ DEBUG(6,("short string '%s'\n", as));
+ }
+ } else {
+ if (strlen(as) == (len2 + c_len_term)) {
+ DEBUG(6,("long string '%s'\n", as));
+ }
+ }
+ *s = as;
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
+ if (len1 == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ } else {
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ (len1 + c_len_term)*byte_mul,
+ &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (strlen(as) < (len1 + c_len_term)) {
+ DEBUG(6,("short string '%s'\n", as));
+ }
+ } else {
+ if (strlen(as) == (len1 + c_len_term)) {
+ DEBUG(6,("long string '%s'\n", as));
+ }
+ }
+ *s = as;
+ break;
+
+ case LIBNDR_FLAG_STR_LEN4:
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+ if (ofs != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
+ if (len1 == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ } else {
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ (len1 + c_len_term)*byte_mul,
+ &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (strlen(as) < (len1 + c_len_term)) {
+ DEBUG(6,("short string '%s'\n", as));
+ }
+ } else {
+ if (strlen(as) == (len1 + c_len_term)) {
+ DEBUG(6,("long string '%s'\n", as));
+ }
+ }
+ *s = as;
+ break;
+
+
+ case LIBNDR_FLAG_STR_SIZE2:
+ case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+ NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
+ if (len3 == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ } else {
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ (len3 + c_len_term)*byte_mul,
+ &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (strlen(as) < (len3 + c_len_term)) {
+ DEBUG(6,("short string '%s'\n", as));
+ }
+ } else {
+ if (strlen(as) == (len3 + c_len_term)) {
+ DEBUG(6,("long string '%s'\n", as));
+ }
+ }
+ *s = as;
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+ NDR_PULL_NEED_BYTES(ndr, len3);
+ if (len3 == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ } else {
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len3, &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, len3));
+ *s = as;
+ break;
+
+ case LIBNDR_FLAG_STR_NULLTERM:
+ if (byte_mul == 1) {
+ len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
+ } else {
+ len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
+ }
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len1, &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, len1));
+ *s = as;
+ break;
+
+ case LIBNDR_FLAG_STR_FIXLEN15:
+ case LIBNDR_FLAG_STR_FIXLEN32:
+ len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
+ NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len1*byte_mul, &as, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
+ *s = as;
+ break;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ push a general string onto the wire
+*/
+NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
+{
+ ssize_t s_len, c_len, d_len;
+ charset_t chset = CH_UTF16LE;
+ unsigned flags = ndr->flags;
+ unsigned byte_mul = 2;
+ uint8_t *dest = NULL;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ if (NDR_BE(ndr)) {
+ chset = CH_UTF16BE;
+ }
+
+ s_len = s?strlen(s):0;
+
+ if (flags & LIBNDR_FLAG_STR_ASCII) {
+ chset = CH_DOS;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_ASCII;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_UTF8) {
+ chset = CH_UTF8;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_UTF8;
+ }
+
+ flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+
+ if (!(flags &
+ (LIBNDR_FLAG_STR_NOTERM |
+ LIBNDR_FLAG_STR_FIXLEN15 |
+ LIBNDR_FLAG_STR_FIXLEN32))) {
+ s_len++;
+ }
+ d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest,
+ False);
+ if (d_len == -1) {
+ return ndr_push_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+
+ if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+ c_len = d_len;
+ flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
+ } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+ c_len = (d_len / byte_mul)-1;
+ flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+ } else {
+ c_len = d_len / byte_mul;
+ }
+
+ switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_LEN4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE2:
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_NULLTERM:
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_FIXLEN15:
+ case LIBNDR_FLAG_STR_FIXLEN32: {
+ ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
+ uint32_t pad_len = fix_len - d_len;
+ if (d_len > fix_len) {
+ return ndr_push_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ if (pad_len != 0) {
+ NDR_CHECK(ndr_push_zero(ndr, pad_len));
+ }
+ break;
+ }
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ talloc_free(dest);
+
+ return NT_STATUS_OK;
+}
+
+/**
+ push a general string onto the wire
+*/
+size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
+{
+ size_t c_len;
+ unsigned flags = ndr->flags;
+ unsigned byte_mul = 2;
+ unsigned c_len_term = 1;
+
+ if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
+ return 32;
+ }
+ if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
+ return 15;
+ }
+
+ c_len = s?strlen(s):0;
+
+ if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
+ byte_mul = 1;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_NOTERM) {
+ c_len_term = 0;
+ }
+
+ c_len = c_len + c_len_term;
+
+ if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+ c_len = c_len * byte_mul;
+ }
+
+ return c_len;
+}
+
+void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
+{
+ if (s) {
+ ndr->print(ndr, "%-25s: '%s'", name, s);
+ } else {
+ ndr->print(ndr, "%-25s: NULL", name);
+ }
+}
+
+uint32_t ndr_size_string(int ret, const char * const* string, int flags)
+{
+ /* FIXME: Is this correct for all strings ? */
+ if(!(*string)) return ret;
+ return ret+strlen(*string)+1;
+}
+
+/**
+ pull a general string array from the wire
+*/
+NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
+{
+ const char **a = *_a;
+ uint32_t count;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ for (count = 0;; count++) {
+ TALLOC_CTX *tmp_ctx;
+ const char *s = NULL;
+ a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
+ NT_STATUS_HAVE_NO_MEMORY(a);
+ a[count] = NULL;
+ a[count+1] = NULL;
+
+ tmp_ctx = ndr->current_mem_ctx;
+ ndr->current_mem_ctx = a;
+ NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+ ndr->current_mem_ctx = tmp_ctx;
+ if (strcmp("", s)==0) {
+ a[count] = NULL;
+ break;
+ } else {
+ a[count] = s;
+ }
+ }
+
+ *_a =a;
+ return NT_STATUS_OK;
+}
+
+/**
+ push a general string array onto the wire
+*/
+NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
+{
+ uint32_t count;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ for (count = 0; a && a[count]; count++) {
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+ }
+
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+
+ return NT_STATUS_OK;
+}
+
+void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
+{
+ uint32_t count;
+ uint32_t i;
+
+ for (count = 0; a && a[count]; count++) {}
+
+ ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+ ndr->depth++;
+ for (i=0;i<count;i++) {
+ char *idx=NULL;
+ asprintf(&idx, "[%d]", i);
+ if (idx) {
+ ndr_print_string(ndr, idx, a[i]);
+ free(idx);
+ }
+ }
+ ndr->depth--;
+}
+
+/**
+ * Return number of elements in a string including the last (zeroed) element
+ */
+uint32_t ndr_string_length(const void *_var, uint32_t element_size)
+{
+ uint32_t i;
+ uint8_t zero[4] = {0,0,0,0};
+ const char *var = (const char *)_var;
+
+ for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
+
+ return i+1;
+}
+
+NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
+{
+ uint32_t i;
+ struct ndr_pull_save save_offset;
+
+ ndr_pull_save(ndr, &save_offset);
+ ndr_pull_advance(ndr, (count - 1) * element_size);
+ NDR_PULL_NEED_BYTES(ndr, element_size);
+
+ for (i = 0; i < element_size; i++) {
+ if (ndr->data[ndr->offset+i] != 0) {
+ ndr_pull_restore(ndr, &save_offset);
+
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
+ }
+ }
+
+ ndr_pull_restore(ndr, &save_offset);
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ int ret;
+ if (length == 0) {
+ *var = talloc_strdup(ndr->current_mem_ctx, "");
+ return NT_STATUS_OK;
+ }
+
+ if (NDR_BE(ndr) && chset == CH_UTF16) {
+ chset = CH_UTF16BE;
+ }
+
+ NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
+
+ ret = convert_string_talloc(ndr->current_mem_ctx,
+ chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ length*byte_mul,
+ var, False);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var,
+ uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ ssize_t ret, required;
+
+ if (NDR_BE(ndr) && chset == CH_UTF16) {
+ chset = CH_UTF16BE;
+ }
+
+ required = byte_mul * length;
+
+ NDR_PUSH_NEED_BYTES(ndr, required);
+ ret = convert_string(CH_UNIX, chset,
+ var, strlen(var),
+ ndr->data+ndr->offset, required, False);
+ if (ret == -1) {
+ return ndr_push_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+
+ /* Make sure the remaining part of the string is filled with zeroes */
+ if (ret < required) {
+ memset(ndr->data+ndr->offset+ret, 0, required-ret);
+ }
+
+ ndr->offset += required;
+
+ return NT_STATUS_OK;
+}
+
+/* Return number of elements in a string in the specified charset */
+uint32_t ndr_charset_length(const void *var, int chset)
+{
+ /* FIXME: Treat special chars special here, taking chset into account */
+ /* Also include 0 byte */
+ return strlen((const char *)var)+1;
+}
diff --git a/source/librpc/ndr/security.h b/source/librpc/ndr/security.h
new file mode 100644
index 00000000000..61e0ea313f7
--- /dev/null
+++ b/source/librpc/ndr/security.h
@@ -0,0 +1,253 @@
+/* header auto-generated by pidl */
+
+#ifndef _HEADER_security
+#define _HEADER_security
+
+#define SEC_MASK_GENERIC ( 0xF0000000 )
+#define SEC_MASK_FLAGS ( 0x0F000000 )
+#define SEC_MASK_STANDARD ( 0x00FF0000 )
+#define SEC_MASK_SPECIFIC ( 0x0000FFFF )
+#define SEC_GENERIC_ALL ( 0x10000000 )
+#define SEC_GENERIC_EXECUTE ( 0x20000000 )
+#define SEC_GENERIC_WRITE ( 0x40000000 )
+#define SEC_GENERIC_READ ( 0x80000000 )
+#define SEC_FLAG_SYSTEM_SECURITY ( 0x01000000 )
+#define SEC_FLAG_MAXIMUM_ALLOWED ( 0x02000000 )
+#define SEC_STD_DELETE ( 0x00010000 )
+#define SEC_STD_READ_CONTROL ( 0x00020000 )
+#define SEC_STD_WRITE_DAC ( 0x00040000 )
+#define SEC_STD_WRITE_OWNER ( 0x00080000 )
+#define SEC_STD_SYNCHRONIZE ( 0x00100000 )
+#define SEC_STD_REQUIRED ( 0x000F0000 )
+#define SEC_STD_ALL ( 0x001F0000 )
+#define SEC_FILE_READ_DATA ( 0x00000001 )
+#define SEC_FILE_WRITE_DATA ( 0x00000002 )
+#define SEC_FILE_APPEND_DATA ( 0x00000004 )
+#define SEC_FILE_READ_EA ( 0x00000008 )
+#define SEC_FILE_WRITE_EA ( 0x00000010 )
+#define SEC_FILE_EXECUTE ( 0x00000020 )
+#define SEC_FILE_READ_ATTRIBUTE ( 0x00000080 )
+#define SEC_FILE_WRITE_ATTRIBUTE ( 0x00000100 )
+#define SEC_FILE_ALL ( 0x000001ff )
+#define SEC_DIR_LIST ( 0x00000001 )
+#define SEC_DIR_ADD_FILE ( 0x00000002 )
+#define SEC_DIR_ADD_SUBDIR ( 0x00000004 )
+#define SEC_DIR_READ_EA ( 0x00000008 )
+#define SEC_DIR_WRITE_EA ( 0x00000010 )
+#define SEC_DIR_TRAVERSE ( 0x00000020 )
+#define SEC_DIR_DELETE_CHILD ( 0x00000040 )
+#define SEC_DIR_READ_ATTRIBUTE ( 0x00000080 )
+#define SEC_DIR_WRITE_ATTRIBUTE ( 0x00000100 )
+#define SEC_REG_QUERY_VALUE ( 0x00000001 )
+#define SEC_REG_SET_VALUE ( 0x00000002 )
+#define SEC_REG_CREATE_SUBKEY ( 0x00000004 )
+#define SEC_REG_ENUM_SUBKEYS ( 0x00000008 )
+#define SEC_REG_NOTIFY ( 0x00000010 )
+#define SEC_REG_CREATE_LINK ( 0x00000020 )
+#define SEC_ADS_CREATE_CHILD ( 0x00000001 )
+#define SEC_ADS_DELETE_CHILD ( 0x00000002 )
+#define SEC_ADS_LIST ( 0x00000004 )
+#define SEC_ADS_SELF_WRITE ( 0x00000008 )
+#define SEC_ADS_READ_PROP ( 0x00000010 )
+#define SEC_ADS_WRITE_PROP ( 0x00000020 )
+#define SEC_ADS_DELETE_TREE ( 0x00000040 )
+#define SEC_ADS_LIST_OBJECT ( 0x00000080 )
+#define SEC_ADS_CONTROL_ACCESS ( 0x00000100 )
+#define SEC_RIGHTS_FILE_READ ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_READ_EA )
+#define SEC_RIGHTS_FILE_WRITE ( SEC_STD_READ_CONTROL|SEC_STD_SYNCHRONIZE|SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_ATTRIBUTE|SEC_FILE_WRITE_EA|SEC_FILE_APPEND_DATA )
+#define SEC_RIGHTS_FILE_EXECUTE ( SEC_STD_SYNCHRONIZE|SEC_STD_READ_CONTROL|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_EXECUTE )
+#define SEC_RIGHTS_FILE_ALL ( SEC_STD_ALL|SEC_FILE_ALL )
+#define SEC_RIGHTS_DIR_READ ( SEC_RIGHTS_FILE_READ )
+#define SEC_RIGHTS_DIR_WRITE ( SEC_RIGHTS_FILE_WRITE )
+#define SEC_RIGHTS_DIR_EXECUTE ( SEC_RIGHTS_FILE_EXECUTE )
+#define SEC_RIGHTS_DIR_ALL ( SEC_RIGHTS_FILE_ALL )
+#define SID_NULL ( "S-1-0-0" )
+#define SID_WORLD_DOMAIN ( "S-1-1" )
+#define SID_WORLD ( "S-1-1-0" )
+#define SID_CREATOR_OWNER_DOMAIN ( "S-1-3" )
+#define SID_CREATOR_OWNER ( "S-1-3-0" )
+#define SID_CREATOR_GROUP ( "S-1-3-1" )
+#define SID_NT_AUTHORITY ( "S-1-5" )
+#define SID_NT_DIALUP ( "S-1-5-1" )
+#define SID_NT_NETWORK ( "S-1-5-2" )
+#define SID_NT_BATCH ( "S-1-5-3" )
+#define SID_NT_INTERACTIVE ( "S-1-5-4" )
+#define SID_NT_SERVICE ( "S-1-5-6" )
+#define SID_NT_ANONYMOUS ( "S-1-5-7" )
+#define SID_NT_PROXY ( "S-1-5-8" )
+#define SID_NT_ENTERPRISE_DCS ( "S-1-5-9" )
+#define SID_NT_SELF ( "S-1-5-10" )
+#define SID_NT_AUTHENTICATED_USERS ( "S-1-5-11" )
+#define SID_NT_RESTRICTED ( "S-1-5-12" )
+#define SID_NT_TERMINAL_SERVER_USERS ( "S-1-5-13" )
+#define SID_NT_REMOTE_INTERACTIVE ( "S-1-5-14" )
+#define SID_NT_THIS_ORGANISATION ( "S-1-5-15" )
+#define SID_NT_SYSTEM ( "S-1-5-18" )
+#define SID_NT_LOCAL_SERVICE ( "S-1-5-19" )
+#define SID_NT_NETWORK_SERVICE ( "S-1-5-20" )
+#define SID_BUILTIN ( "S-1-5-32" )
+#define SID_BUILTIN_ADMINISTRATORS ( "S-1-5-32-544" )
+#define SID_BUILTIN_USERS ( "S-1-5-32-545" )
+#define SID_BUILTIN_GUESTS ( "S-1-5-32-546" )
+#define SID_BUILTIN_POWER_USERS ( "S-1-5-32-547" )
+#define SID_BUILTIN_ACCOUNT_OPERATORS ( "S-1-5-32-548" )
+#define SID_BUILTIN_SERVER_OPERATORS ( "S-1-5-32-549" )
+#define SID_BUILTIN_PRINT_OPERATORS ( "S-1-5-32-550" )
+#define SID_BUILTIN_BACKUP_OPERATORS ( "S-1-5-32-551" )
+#define SID_BUILTIN_REPLICATOR ( "S-1-5-32-552" )
+#define SID_BUILTIN_RAS_SERVERS ( "S-1-5-32-553" )
+#define SID_BUILTIN_PREW2K ( "S-1-5-32-554" )
+#define DOMAIN_RID_LOGON ( 9 )
+#define DOMAIN_RID_ADMINISTRATOR ( 500 )
+#define DOMAIN_RID_GUEST ( 501 )
+#define DOMAIN_RID_ADMINS ( 512 )
+#define DOMAIN_RID_USERS ( 513 )
+#define DOMAIN_RID_DCS ( 516 )
+#define DOMAIN_RID_CERT_ADMINS ( 517 )
+#define DOMAIN_RID_SCHEMA_ADMINS ( 518 )
+#define DOMAIN_RID_ENTERPRISE_ADMINS ( 519 )
+#define NT4_ACL_REVISION ( SECURITY_ACL_REVISION_NT4 )
+#define SD_REVISION ( SECURITY_DESCRIPTOR_REVISION_1 )
+enum sec_privilege {
+ SEC_PRIV_SECURITY=1,
+ SEC_PRIV_BACKUP=2,
+ SEC_PRIV_RESTORE=3,
+ SEC_PRIV_SYSTEMTIME=4,
+ SEC_PRIV_SHUTDOWN=5,
+ SEC_PRIV_REMOTE_SHUTDOWN=6,
+ SEC_PRIV_TAKE_OWNERSHIP=7,
+ SEC_PRIV_DEBUG=8,
+ SEC_PRIV_SYSTEM_ENVIRONMENT=9,
+ SEC_PRIV_SYSTEM_PROFILE=10,
+ SEC_PRIV_PROFILE_SINGLE_PROCESS=11,
+ SEC_PRIV_INCREASE_BASE_PRIORITY=12,
+ SEC_PRIV_LOAD_DRIVER=13,
+ SEC_PRIV_CREATE_PAGEFILE=14,
+ SEC_PRIV_INCREASE_QUOTA=15,
+ SEC_PRIV_CHANGE_NOTIFY=16,
+ SEC_PRIV_UNDOCK=17,
+ SEC_PRIV_MANAGE_VOLUME=18,
+ SEC_PRIV_IMPERSONATE=19,
+ SEC_PRIV_CREATE_GLOBAL=20,
+ SEC_PRIV_ENABLE_DELEGATION=21,
+ SEC_PRIV_INTERACTIVE_LOGON=22,
+ SEC_PRIV_NETWORK_LOGON=23,
+ SEC_PRIV_REMOTE_INTERACTIVE_LOGON=24
+};
+
+/* bitmap security_ace_flags */
+#define SEC_ACE_FLAG_OBJECT_INHERIT ( 0x01 )
+#define SEC_ACE_FLAG_CONTAINER_INHERIT ( 0x02 )
+#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT ( 0x04 )
+#define SEC_ACE_FLAG_INHERIT_ONLY ( 0x08 )
+#define SEC_ACE_FLAG_INHERITED_ACE ( 0x10 )
+#define SEC_ACE_FLAG_VALID_INHERIT ( 0x0f )
+#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
+#define SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 )
+
+enum security_ace_type {
+ SEC_ACE_TYPE_ACCESS_ALLOWED=0,
+ SEC_ACE_TYPE_ACCESS_DENIED=1,
+ SEC_ACE_TYPE_SYSTEM_AUDIT=2,
+ SEC_ACE_TYPE_SYSTEM_ALARM=3,
+ SEC_ACE_TYPE_ALLOWED_COMPOUND=4,
+ SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT=5,
+ SEC_ACE_TYPE_ACCESS_DENIED_OBJECT=6,
+ SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT=7,
+ SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT=8
+};
+
+/* bitmap security_ace_object_flags */
+#define SEC_ACE_OBJECT_TYPE_PRESENT ( 0x00000001 )
+#define SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT ( 0x00000002 )
+
+union security_ace_object_type {
+ struct GUID type;/* [case(SEC_ACE_OBJECT_TYPE_PRESENT)] */
+}/* [nodiscriminant] */;
+
+union security_ace_object_inherited_type {
+ struct GUID inherited_type;/* [case(SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */
+}/* [nodiscriminant] */;
+
+struct security_ace_object {
+ uint32_t flags;
+ union security_ace_object_type type;/* [switch_is(flags&SEC_ACE_OBJECT_TYPE_PRESENT)] */
+ union security_ace_object_inherited_type inherited_type;/* [switch_is(flags&SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)] */
+};
+
+union security_ace_object_ctr {
+ struct security_ace_object object;/* [case(SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT)] */
+}/* [nodiscriminant] */;
+
+struct security_ace {
+ enum security_ace_type type;
+ uint8_t flags;
+ uint16_t size;/* [value(ndr_size_security_ace(r,ndr->flags))] */
+ uint32_t access_mask;
+ union security_ace_object_ctr object;/* [switch_is(type)] */
+ struct dom_sid trustee;
+}/* [gensize,public,nosize] */;
+
+enum security_acl_revision {
+ SECURITY_ACL_REVISION_NT4=2,
+ SECURITY_ACL_REVISION_ADS=4
+};
+
+struct security_acl {
+ enum security_acl_revision revision;
+ uint16_t size;/* [value(ndr_size_security_acl(r,ndr->flags))] */
+ uint32_t num_aces;/* [range(0 1000)] */
+ struct security_ace *aces;
+}/* [gensize,public,nosize] */;
+
+enum security_descriptor_revision {
+ SECURITY_DESCRIPTOR_REVISION_1=1
+};
+
+/* bitmap security_descriptor_type */
+#define SEC_DESC_OWNER_DEFAULTED ( 0x0001 )
+#define SEC_DESC_GROUP_DEFAULTED ( 0x0002 )
+#define SEC_DESC_DACL_PRESENT ( 0x0004 )
+#define SEC_DESC_DACL_DEFAULTED ( 0x0008 )
+#define SEC_DESC_SACL_PRESENT ( 0x0010 )
+#define SEC_DESC_SACL_DEFAULTED ( 0x0020 )
+#define SEC_DESC_DACL_TRUSTED ( 0x0040 )
+#define SEC_DESC_SERVER_SECURITY ( 0x0080 )
+#define SEC_DESC_DACL_AUTO_INHERIT_REQ ( 0x0100 )
+#define SEC_DESC_SACL_AUTO_INHERIT_REQ ( 0x0200 )
+#define SEC_DESC_DACL_AUTO_INHERITED ( 0x0400 )
+#define SEC_DESC_SACL_AUTO_INHERITED ( 0x0800 )
+#define SEC_DESC_DACL_PROTECTED ( 0x1000 )
+#define SEC_DESC_SACL_PROTECTED ( 0x2000 )
+#define SEC_DESC_RM_CONTROL_VALID ( 0x4000 )
+#define SEC_DESC_SELF_RELATIVE ( 0x8000 )
+
+struct security_descriptor {
+ enum security_descriptor_revision revision;
+ uint16_t type;
+ struct dom_sid *owner_sid;/* [relative] */
+ struct dom_sid *group_sid;/* [relative] */
+ struct security_acl *sacl;/* [relative] */
+ struct security_acl *dacl;/* [relative] */
+}/* [gensize,public,flag(LIBNDR_FLAG_LITTLE_ENDIAN),nosize] */;
+
+struct sec_desc_buf {
+ uint32_t sd_size;/* [value(ndr_size_security_descriptor(sd,ndr->flags)),range(0 0x40000)] */
+ struct security_descriptor *sd;/* [unique,subcontext(4)] */
+}/* [public] */;
+
+struct security_token {
+ struct dom_sid *user_sid;/* [unique] */
+ struct dom_sid *group_sid;/* [unique] */
+ uint32_t num_sids;
+ struct dom_sid **sids;/* [unique,size_is(num_sids)] */
+ uint64_t privilege_mask;
+}/* [public] */;
+
+/* bitmap security_secinfo */
+#define SECINFO_OWNER ( 0x00000001 )
+#define SECINFO_GROUP ( 0x00000002 )
+#define SECINFO_DACL ( 0x00000004 )
+#define SECINFO_SACL ( 0x00000008 )
+
+#endif /* _HEADER_security */
diff --git a/source/librpc/ndr/sid.c b/source/librpc/ndr/sid.c
new file mode 100644
index 00000000000..0a9ddb883b2
--- /dev/null
+++ b/source/librpc/ndr/sid.c
@@ -0,0 +1,252 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr interface
+
+ Copyright (C) Andrew Tridgell 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
+{
+ uint32_t cntr_sub_auths_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
+ NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+ for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
+{
+ uint32_t cntr_sub_auths_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_auths));
+ if (r->num_auths > 15) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+ for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ convert a dom_sid to a string
+*/
+char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
+{
+ int i, ofs, maxlen;
+ uint32_t ia;
+ char *ret;
+
+ if (!sid) {
+ return talloc_strdup(mem_ctx, "(NULL SID)");
+ }
+
+ maxlen = sid->num_auths * 11 + 25;
+ ret = (char *)talloc_size(mem_ctx, maxlen);
+ if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)");
+
+ ia = (sid->id_auth[5]) +
+ (sid->id_auth[4] << 8 ) +
+ (sid->id_auth[3] << 16) +
+ (sid->id_auth[2] << 24);
+
+ ofs = snprintf(ret, maxlen, "S-%u-%lu",
+ (unsigned int)sid->sid_rev_num, (unsigned long)ia);
+
+ for (i = 0; i < sid->num_auths; i++) {
+ ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]);
+ }
+
+ return ret;
+}
+
+/*
+ parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+ uint32_t num_auths;
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
+ if (sid->num_auths != num_auths) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size %u should exceed %u",
+ num_auths, sid->num_auths);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
+ return ndr_push_dom_sid(ndr, ndr_flags, sid);
+}
+
+/*
+ parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only upto 5 sub_auth
+*/
+NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+ NTSTATUS status;
+ struct ndr_pull *subndr;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ subndr = talloc_zero(ndr, struct ndr_pull);
+ NT_STATUS_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags;
+ subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+ subndr->data = ndr->data + ndr->offset;
+ subndr->data_size = 28;
+ subndr->offset = 0;
+
+ NDR_CHECK(ndr_pull_advance(ndr, 28));
+
+ status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* handle a w2k bug which send random data in the buffer */
+ ZERO_STRUCTP(sid);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
+*/
+NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+ uint32_t old_offset;
+ uint32_t padding;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NT_STATUS_OK;
+ }
+
+ if (sid->num_auths > 5) {
+ return ndr_push_error(ndr, NDR_ERR_RANGE,
+ "dom_sid28 allows only upto 5 sub auth [%u]",
+ sid->num_auths);
+ }
+
+ old_offset = ndr->offset;
+ NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
+
+ padding = 28 - (ndr->offset - old_offset);
+
+ if (padding > 0) {
+ NDR_CHECK(ndr_push_zero(ndr, padding));
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_push_sec_desc_buf(struct ndr_push *ndr, int ndr_flags, const struct sec_desc_buf *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_security_descriptor(r->sd,ndr->flags)));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->sd) {
+ {
+ struct ndr_push *_ndr_sd;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sd, 4, -1));
+ NDR_CHECK(ndr_push_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sd, 4, -1));
+ }
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ndr_pull_sec_desc_buf(struct ndr_pull *ndr, int ndr_flags, struct sec_desc_buf *r)
+{
+ uint32_t _ptr_sd;
+ TALLOC_CTX *_mem_save_sd_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sd_size));
+ if (r->sd_size < 0 || r->sd_size > 0x40000) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd));
+ if (_ptr_sd) {
+ NDR_PULL_ALLOC(ndr, r->sd);
+ } else {
+ r->sd = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->sd) {
+ _mem_save_sd_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->sd, 0);
+ {
+ struct ndr_pull *_ndr_sd;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sd, 4, -1));
+ NDR_CHECK(ndr_pull_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sd, 4, -1));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_0, 0);
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+void ndr_print_sec_desc_buf(struct ndr_print *ndr, const char *name, const struct sec_desc_buf *r)
+{
+ ndr_print_struct(ndr, name, "sec_desc_buf");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "sd_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_descriptor(r->sd,ndr->flags):r->sd_size);
+ ndr_print_ptr(ndr, "sd", r->sd);
+ ndr->depth++;
+ if (r->sd) {
+ ndr_print_security_descriptor(ndr, "sd", r->sd);
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
diff --git a/source/libsmb/asn1.c b/source/libsmb/asn1.c
index 544ee78d406..6ebe9ab62cf 100644
--- a/source/libsmb/asn1.c
+++ b/source/libsmb/asn1.c
@@ -23,6 +23,14 @@
/* free an asn1 structure */
void asn1_free(ASN1_DATA *data)
{
+ struct nesting *nesting = data->nesting;
+
+ while (nesting) {
+ struct nesting *nnext = nesting->next;
+ free(nesting);
+ nesting = nnext;
+ };
+ data->nesting = NULL;
SAFE_FREE(data->data);
}
@@ -31,7 +39,8 @@ BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
{
if (data->has_error) return False;
if (data->length < data->ofs+len) {
- data->data = SMB_REALLOC(data->data, data->ofs+len);
+ data->data = SMB_REALLOC_ARRAY(data->data, unsigned char,
+ data->ofs+len);
if (!data->data) {
data->has_error = True;
return False;
@@ -73,6 +82,10 @@ BOOL asn1_pop_tag(ASN1_DATA *data)
struct nesting *nesting;
size_t len;
+ if (data->has_error) {
+ return False;
+ }
+
nesting = data->nesting;
if (!nesting) {
@@ -213,7 +226,7 @@ BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
BOOL asn1_load(ASN1_DATA *data, DATA_BLOB blob)
{
ZERO_STRUCTP(data);
- data->data = memdup(blob.data, blob.length);
+ data->data = (unsigned char *)memdup(blob.data, blob.length);
if (!data->data) {
data->has_error = True;
return False;
@@ -405,7 +418,7 @@ BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
data->has_error = True;
return False;
}
- str = SMB_MALLOC(len+1);
+ str = SMB_MALLOC_ARRAY(char, len+1);
if (!str) {
data->has_error = True;
return False;
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index c51da644a11..e2213c1fcde 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -33,6 +33,7 @@ static const struct {
{PROTOCOL_LANMAN1,"LANMAN1.0"},
{PROTOCOL_LANMAN2,"LM1.2X002"},
{PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
+ {PROTOCOL_LANMAN2,"LANMAN2.1"},
{PROTOCOL_LANMAN2,"Samba"},
{PROTOCOL_NT1,"NT LANMAN 1.0"},
{PROTOCOL_NT1,"NT LM 0.12"},
@@ -55,16 +56,19 @@ static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_
Do an old lanman2 style session setup.
****************************************************************************/
-static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
- const char *pass, size_t passlen, const char *workgroup)
+static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
+ const char *user,
+ const char *pass, size_t passlen,
+ const char *workgroup)
{
DATA_BLOB session_key = data_blob(NULL, 0);
DATA_BLOB lm_response = data_blob(NULL, 0);
fstring pword;
char *p;
- if (passlen > sizeof(pword)-1)
- return False;
+ if (passlen > sizeof(pword)-1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
/* LANMAN servers predate NT status codes and Unicode and ignore those
smb flags so we must disable the corresponding default capabilities
@@ -82,7 +86,7 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
lm_response = data_blob(NULL, 24);
if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
} else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
/* Encrypted mode needed, and encrypted password supplied. */
@@ -115,14 +119,15 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
+ return cli_nt_error(cli);
+ }
show_msg(cli->inbuf);
- if (cli_is_error(cli))
- return False;
+ if (cli_is_error(cli)) {
+ return cli_nt_error(cli);
+ }
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -133,7 +138,7 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
cli_set_session_key(cli, session_key);
}
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -158,7 +163,7 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
Do a NT1 guest session setup.
****************************************************************************/
-static BOOL cli_session_setup_guest(struct cli_state *cli)
+static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
{
char *p;
uint32 capabilities = cli_session_setup_capabilities(cli);
@@ -183,14 +188,15 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
+ return cli_nt_error(cli);
+ }
show_msg(cli->inbuf);
- if (cli_is_error(cli))
- return False;
+ if (cli_is_error(cli)) {
+ return cli_nt_error(cli);
+ }
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -205,15 +211,16 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
fstrcpy(cli->user_name, "");
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
Do a NT1 plaintext session setup.
****************************************************************************/
-static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
- const char *pass, const char *workgroup)
+static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
+ const char *user, const char *pass,
+ const char *workgroup)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
char *p;
@@ -252,14 +259,15 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
+ return cli_nt_error(cli);
+ }
show_msg(cli->inbuf);
- if (cli_is_error(cli))
- return False;
+ if (cli_is_error(cli)) {
+ return cli_nt_error(cli);
+ }
cli->vuid = SVAL(cli->inbuf,smb_uid);
p = smb_buf(cli->inbuf);
@@ -272,7 +280,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
cli->is_samba = True;
}
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -285,16 +293,16 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
@param workgroup The user's domain.
****************************************************************************/
-static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
- const char *pass, size_t passlen,
- const char *ntpass, size_t ntpasslen,
- const char *workgroup)
+static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
+ const char *pass, size_t passlen,
+ const char *ntpass, size_t ntpasslen,
+ const char *workgroup)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
DATA_BLOB lm_response = data_blob(NULL, 0);
DATA_BLOB nt_response = data_blob(NULL, 0);
DATA_BLOB session_key = data_blob(NULL, 0);
- BOOL ret = False;
+ NTSTATUS result;
char *p;
if (passlen == 0) {
@@ -316,7 +324,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
&lm_response, &nt_response, &session_key)) {
data_blob_free(&names_blob);
data_blob_free(&server_chal);
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
data_blob_free(&names_blob);
data_blob_free(&server_chal);
@@ -398,14 +406,14 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
cli_setup_bcc(cli, p);
if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
- ret = False;
+ result = cli_nt_error(cli);
goto end;
}
/* show_msg(cli->inbuf); */
if (cli_is_error(cli)) {
- ret = False;
+ result = cli_nt_error(cli);
goto end;
}
@@ -428,12 +436,12 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
cli_set_session_key(cli, session_key);
}
- ret = True;
+ result = NT_STATUS_OK;
end:
data_blob_free(&lm_response);
data_blob_free(&nt_response);
data_blob_free(&session_key);
- return ret;
+ return result;
}
/****************************************************************************
@@ -509,19 +517,76 @@ static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
}
#ifdef HAVE_KRB5
-
/****************************************************************************
Send a extended security session setup blob, returning a reply blob.
****************************************************************************/
-static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
+/* The following is calculated from :
+ * (smb_size-4) = 35
+ * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
+ * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
+ * end of packet.
+ */
+
+#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
+
+static BOOL cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_BLOB session_key_krb5)
{
- DATA_BLOB blob2 = data_blob(NULL, 0);
- if (!cli_session_setup_blob_send(cli, blob)) {
- return blob2;
+ int32 remaining = blob.length;
+ int32 cur = 0;
+ DATA_BLOB send_blob = data_blob(NULL, 0);
+ int32 max_blob_size = 0;
+
+ if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
+ DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
+ "(was %u, need minimum %u)\n",
+ (unsigned int)cli->max_xmit,
+ BASE_SESSSETUP_BLOB_PACKET_SIZE));
+ cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
+ return False;
}
-
- return cli_session_setup_blob_receive(cli);
+
+ max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
+
+ while ( remaining > 0) {
+ if (remaining >= max_blob_size) {
+ send_blob.length = max_blob_size;
+ remaining -= max_blob_size;
+ } else {
+ DATA_BLOB null_blob = data_blob(NULL, 0);
+
+ send_blob.length = remaining;
+ remaining = 0;
+
+ /* This is the last packet in the sequence - turn signing on. */
+ cli_simple_set_signing(cli, session_key_krb5, null_blob);
+ }
+
+ send_blob.data = &blob.data[cur];
+ cur += send_blob.length;
+
+ DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
+ (unsigned int)remaining,
+ (unsigned int)send_blob.length,
+ (unsigned int)cur ));
+
+ if (!cli_session_setup_blob_send(cli, send_blob)) {
+ DEBUG(0, ("cli_session_setup_blob: send failed\n"));
+ return False;
+ }
+
+ cli_session_setup_blob_receive(cli);
+
+ if (cli_is_error(cli) &&
+ !NT_STATUS_EQUAL( cli_get_nt_error(cli),
+ NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
+ nt_errstr(cli_get_nt_error(cli)) ));
+ return False;
+ }
+ }
+
+ return True;
}
/****************************************************************************
@@ -538,18 +603,18 @@ static void use_in_memory_ccache(void) {
static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
{
- DATA_BLOB blob2, negTokenTarg;
+ DATA_BLOB negTokenTarg;
DATA_BLOB session_key_krb5;
- DATA_BLOB null_blob = data_blob(NULL, 0);
int rc;
DEBUG(2,("Doing kerberos session setup\n"));
/* generate the encapsulated kerberos5 ticket */
- rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0);
+ rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
if (rc) {
- DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
+ DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
+ error_message(rc)));
return ADS_ERROR_KRB5(rc);
}
@@ -557,12 +622,11 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
#endif
- cli_simple_set_signing(cli, session_key_krb5, null_blob);
-
- blob2 = cli_session_setup_blob(cli, negTokenTarg);
-
- /* we don't need this blob for kerberos */
- data_blob_free(&blob2);
+ if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
+ data_blob_free(&negTokenTarg);
+ data_blob_free(&session_key_krb5);
+ ADS_ERROR_NT(cli_nt_error(cli));
+ }
cli_set_session_key(cli, session_key_krb5);
@@ -599,6 +663,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
return nt_status;
}
+ ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
return nt_status;
@@ -761,7 +826,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
* sent. -- VL
*/
DEBUG(1, ("Kerberos mech was offered, but no principal was "
- "sent, disabling Kerberos\n"));
+ "sent, disabling Kerberos\n"));
cli->use_kerberos = False;
}
@@ -810,11 +875,11 @@ ntlmssp:
password is in plaintext, the same should be done.
****************************************************************************/
-BOOL cli_session_setup(struct cli_state *cli,
- const char *user,
- const char *pass, int passlen,
- const char *ntpass, int ntpasslen,
- const char *workgroup)
+NTSTATUS cli_session_setup(struct cli_state *cli,
+ const char *user,
+ const char *pass, int passlen,
+ const char *ntpass, int ntpasslen,
+ const char *workgroup)
{
char *p;
fstring user2;
@@ -828,8 +893,9 @@ BOOL cli_session_setup(struct cli_state *cli,
workgroup = user2;
}
- if (cli->protocol < PROTOCOL_LANMAN1)
- return True;
+ if (cli->protocol < PROTOCOL_LANMAN1) {
+ return NT_STATUS_OK;
+ }
/* now work out what sort of session setup we are going to
do. I have split this into separate functions to make the
@@ -841,17 +907,18 @@ BOOL cli_session_setup(struct cli_state *cli,
if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
DEBUG(1, ("Server requested LM password but 'client lanman auth'"
" is disabled\n"));
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
" is disabled\n"));
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
- return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
+ return cli_session_setup_lanman2(cli, user, pass, passlen,
+ workgroup);
}
/* if no user is supplied then we have to do an anonymous connection.
@@ -874,7 +941,7 @@ BOOL cli_session_setup(struct cli_state *cli,
if (!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
" is disabled\n"));
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
return cli_session_setup_plaintext(cli, user, pass, workgroup);
}
@@ -885,13 +952,18 @@ BOOL cli_session_setup(struct cli_state *cli,
ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
if (!ADS_ERR_OK(status)) {
DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
- return False;
+ return ads_ntstatus(status);
}
} else {
+ NTSTATUS status;
+
/* otherwise do a NT1 style session setup */
- if ( !cli_session_setup_nt1(cli, user, pass, passlen, ntpass, ntpasslen, workgroup) ) {
- DEBUG(3,("cli_session_setup: NT1 session setup failed!\n"));
- return False;
+ status = cli_session_setup_nt1(cli, user, pass, passlen,
+ ntpass, ntpasslen, workgroup);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("cli_session_setup: NT1 session setup "
+ "failed: %s\n", nt_errstr(status)));
+ return status;
}
}
@@ -899,7 +971,7 @@ BOOL cli_session_setup(struct cli_state *cli,
cli->is_samba = True;
}
- return True;
+ return NT_STATUS_OK;
}
@@ -1143,6 +1215,7 @@ BOOL cli_negprot(struct cli_state *cli)
}
if (cli->protocol >= PROTOCOL_NT1) {
+ struct timespec ts;
/* NT protocol */
cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
@@ -1151,7 +1224,8 @@ BOOL cli_negprot(struct cli_state *cli)
cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
cli->serverzone *= 60;
/* this time arrives in real GMT */
- cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
+ ts = interpret_long_date(cli->inbuf+smb_vwv11+1);
+ cli->servertime = ts.tv_sec;
cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
if (cli->capabilities & CAP_RAW_MODE) {
@@ -1403,8 +1477,9 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
if (!my_name)
my_name = global_myname();
- if (!(cli = cli_initialise(NULL)))
+ if (!(cli = cli_initialise())) {
return NT_STATUS_NO_MEMORY;
+ }
make_nmb_name(&calling, my_name, 0x0);
make_nmb_name(&called , dest_host, 0x20);
@@ -1504,6 +1579,8 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
struct cli_state *cli = NULL;
int pw_len = password ? strlen(password)+1 : 0;
+ *output_cli = NULL;
+
if (password == NULL) {
password = "";
}
@@ -1515,19 +1592,26 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
return nt_status;
}
- if (!cli_session_setup(cli, user, password, pw_len, password, pw_len, domain)) {
- if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
- && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
- } else {
- nt_status = cli_nt_error(cli);
- DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
+ nt_status = cli_session_setup(cli, user, password, pw_len, password,
+ pw_len, domain);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+
+ if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
+ DEBUG(1,("failed session setup with %s\n",
+ nt_errstr(nt_status)));
cli_shutdown(cli);
- if (NT_STATUS_IS_OK(nt_status))
- nt_status = NT_STATUS_UNSUCCESSFUL;
return nt_status;
}
- }
+ nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1,("anonymous failed session setup with %s\n",
+ nt_errstr(nt_status)));
+ cli_shutdown(cli);
+ return nt_status;
+ }
+ }
+
if (service) {
if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
nt_status = cli_nt_error(cli);
@@ -1550,7 +1634,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
****************************************************************************/
-BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
+BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
struct in_addr *pdest_ip)
{
struct nmb_name calling, called;
@@ -1562,12 +1646,13 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost,
* then use *SMBSERVER immediately.
*/
- if(is_ipaddress(desthost))
+ if(is_ipaddress(desthost)) {
make_nmb_name(&called, "*SMBSERVER", 0x20);
- else
+ } else {
make_nmb_name(&called, desthost, 0x20);
+ }
- if (!cli_session_request(cli, &calling, &called)) {
+ if (!cli_session_request(*ppcli, &calling, &called)) {
struct nmb_name smbservername;
make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
@@ -1584,23 +1669,23 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost,
*/
DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
-with error %s.\n", desthost, cli_errstr(cli) ));
+with error %s.\n", desthost, cli_errstr(*ppcli) ));
return False;
}
- /*
- * We need to close the connection here but can't call cli_shutdown as
- * will free an allocated cli struct. cli_close_connection was invented
- * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
- */
+ /* Try again... */
+ cli_shutdown(*ppcli);
- cli_close_connection(cli);
+ *ppcli = cli_initialise();
+ if (!*ppcli) {
+ /* Out of memory... */
+ return False;
+ }
- if (!cli_initialise(cli) ||
- !cli_connect(cli, desthost, pdest_ip) ||
- !cli_session_request(cli, &calling, &smbservername)) {
+ if (!cli_connect(*ppcli, desthost, pdest_ip) ||
+ !cli_session_request(*ppcli, &calling, &smbservername)) {
DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
-name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
+name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
return False;
}
}
@@ -1669,7 +1754,7 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
user_info->username, lp_workgroup(), user_info->password,
- CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
+ CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK, Undefined, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
index e0c55057675..916e4cefc6e 100644
--- a/source/libsmb/clidfs.c
+++ b/source/libsmb/clidfs.c
@@ -51,7 +51,7 @@ static struct client_connection *connections;
static struct cli_state *do_connect( const char *server, const char *share,
BOOL show_sessetup )
{
- struct cli_state *c;
+ struct cli_state *c = NULL;
struct nmb_name called, calling;
const char *server_n;
struct in_addr ip;
@@ -83,7 +83,7 @@ static struct cli_state *do_connect( const char *server, const char *share,
ip = dest_ip;
/* have to open a new connection */
- if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) ||
+ if (!(c=cli_initialise()) || (cli_set_port(c, port) != port) ||
!cli_connect(c, server_n, &ip)) {
d_printf("Connection to %s failed\n", server_n);
return NULL;
@@ -99,6 +99,7 @@ static struct cli_state *do_connect( const char *server, const char *share,
d_printf("session request to %s failed (%s)\n",
called.name, cli_errstr(c));
cli_shutdown(c);
+ c = NULL;
if ((p=strchr_m(called.name, '.'))) {
*p = 0;
goto again;
@@ -126,13 +127,14 @@ static struct cli_state *do_connect( const char *server, const char *share,
}
}
- if (!cli_session_setup(c, username,
- password, strlen(password),
- password, strlen(password),
- lp_workgroup())) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
+ password, strlen(password),
+ password, strlen(password),
+ lp_workgroup()))) {
/* if a password was not supplied then try again with a null username */
if (password[0] || !username[0] || use_kerberos ||
- !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) {
+ !NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0, "", 0,
+ lp_workgroup()))) {
d_printf("session setup failed: %s\n", cli_errstr(c));
if (NT_STATUS_V(cli_nt_error(c)) ==
NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
diff --git a/source/libsmb/clidgram.c b/source/libsmb/clidgram.c
index dfb613238f6..a983f485ab4 100644
--- a/source/libsmb/clidgram.c
+++ b/source/libsmb/clidgram.c
@@ -101,8 +101,9 @@ BOOL cli_send_mailslot(BOOL unique, const char *mailslot,
DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name),
inet_ntoa(dest_ip)));
- return message_send_pid(pid_to_procid(nmbd_pid), MSG_SEND_PACKET, &p, sizeof(p),
- False);
+ return NT_STATUS_IS_OK(message_send_pid(pid_to_procid(nmbd_pid),
+ MSG_SEND_PACKET, &p, sizeof(p),
+ False));
}
/*
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 8342df0f1d1..68ecb131b11 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -20,6 +20,8 @@
#include "includes.h"
+extern int smb_read_error;
+
/****************************************************************************
Change the timeout (in milliseconds).
****************************************************************************/
@@ -79,7 +81,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) */
@@ -107,8 +108,8 @@ BOOL cli_receive_smb(struct cli_state *cli)
}
/* If the server is not responding, note that now */
-
if (!ret) {
+ DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
cli->smb_rw_error = smb_read_error;
close(cli->fd);
cli->fd = -1;
@@ -255,12 +256,12 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state)
}
/****************************************************************************
- Initialise a client structure.
+ Initialise a client structure. Always returns a malloc'ed struct.
****************************************************************************/
-struct cli_state *cli_initialise(struct cli_state *cli)
+struct cli_state *cli_initialise(void)
{
- BOOL alloced_cli = False;
+ struct cli_state *cli = NULL;
/* Check the effective uid - make sure we are not setuid */
if (is_setuid_root()) {
@@ -268,17 +269,11 @@ struct cli_state *cli_initialise(struct cli_state *cli)
return NULL;
}
+ cli = SMB_MALLOC_P(struct cli_state);
if (!cli) {
- cli = SMB_MALLOC_P(struct cli_state);
- if (!cli)
- return NULL;
- ZERO_STRUCTP(cli);
- alloced_cli = True;
+ return NULL;
}
- if (cli->initialised)
- cli_close_connection(cli);
-
ZERO_STRUCTP(cli);
cli->port = 0;
@@ -333,7 +328,6 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli_null_set_signing(cli);
cli->initialised = 1;
- cli->allocated = alloced_cli;
return cli;
@@ -343,10 +337,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
SAFE_FREE(cli->inbuf);
SAFE_FREE(cli->outbuf);
-
- if (alloced_cli)
- SAFE_FREE(cli);
-
+ SAFE_FREE(cli);
return NULL;
}
@@ -403,10 +394,10 @@ void cli_nt_pipes_close(struct cli_state *cli)
}
/****************************************************************************
- Close a client connection and free the memory without destroying cli itself.
+ Shutdown a client structure.
****************************************************************************/
-void cli_close_connection(struct cli_state *cli)
+void cli_shutdown(struct cli_state *cli)
{
cli_nt_pipes_close(cli);
@@ -443,20 +434,8 @@ void cli_close_connection(struct cli_state *cli)
}
cli->fd = -1;
cli->smb_rw_error = 0;
-}
-/****************************************************************************
- Shutdown a client structure.
-****************************************************************************/
-
-void cli_shutdown(struct cli_state *cli)
-{
- BOOL allocated = cli->allocated;
- cli_close_connection(cli);
- ZERO_STRUCTP(cli);
- if (allocated) {
- free(cli);
- }
+ SAFE_FREE(cli);
}
/****************************************************************************
diff --git a/source/libsmb/clierror.c b/source/libsmb/clierror.c
index 44573bd29b1..f85fc5c5522 100644
--- a/source/libsmb/clierror.c
+++ b/source/libsmb/clierror.c
@@ -226,7 +226,7 @@ void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
}
/* Return a UNIX errno from a NT status code */
-static struct {
+static const struct {
NTSTATUS status;
int error;
} nt_errno_map[] = {
@@ -451,3 +451,12 @@ NTSTATUS cli_get_nt_error(struct cli_state *cli)
return NT_STATUS_UNSUCCESSFUL;
}
}
+
+/* Push an error code into the inbuf to be returned on the next
+ * query. */
+
+void cli_set_nt_error(struct cli_state *cli, NTSTATUS status)
+{
+ SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
+ SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status));
+}
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index ea6501dac89..6328a1720a6 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -266,9 +266,10 @@ BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbu
/* assume 512 byte blocks */
sbuf->st_blocks /= 512;
#endif
- sbuf->st_ctime = interpret_long_date(rdata + 16); /* time of last change */
- sbuf->st_atime = interpret_long_date(rdata + 24); /* time of last access */
- sbuf->st_mtime = interpret_long_date(rdata + 32); /* time of last modification */
+ set_ctimespec(sbuf, interpret_long_date(rdata + 16)); /* time of last change */
+ set_atimespec(sbuf, interpret_long_date(rdata + 24)); /* time of last access */
+ set_mtimespec(sbuf, interpret_long_date(rdata + 32)); /* time of last modification */
+
sbuf->st_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */
sbuf->st_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */
sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56));
@@ -493,7 +494,7 @@ BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *f
Delete a file.
****************************************************************************/
-BOOL cli_unlink(struct cli_state *cli, const char *fname)
+BOOL cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
{
char *p;
@@ -506,7 +507,7 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
- SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
+ SSVAL(cli->outbuf,smb_vwv0, attrs);
p = smb_buf(cli->outbuf);
*p++ = 4;
@@ -526,6 +527,15 @@ BOOL cli_unlink(struct cli_state *cli, const char *fname)
}
/****************************************************************************
+ Delete a file.
+****************************************************************************/
+
+BOOL cli_unlink(struct cli_state *cli, const char *fname)
+{
+ return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
+}
+
+/****************************************************************************
Create a directory.
****************************************************************************/
@@ -1178,7 +1188,9 @@ BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, S
BOOL cli_getattrE(struct cli_state *cli, int fd,
uint16 *attr, SMB_OFF_T *size,
- time_t *c_time, time_t *a_time, time_t *m_time)
+ time_t *change_time,
+ time_t *access_time,
+ time_t *write_time)
{
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
@@ -1208,16 +1220,16 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
*attr = SVAL(cli->inbuf,smb_vwv10);
}
- if (c_time) {
- *c_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
+ if (change_time) {
+ *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
}
- if (a_time) {
- *a_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
+ if (access_time) {
+ *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
}
- if (m_time) {
- *m_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
+ if (write_time) {
+ *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
}
return True;
@@ -1228,7 +1240,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
****************************************************************************/
BOOL cli_getatr(struct cli_state *cli, const char *fname,
- uint16 *attr, SMB_OFF_T *size, time_t *t)
+ uint16 *attr, SMB_OFF_T *size, time_t *write_time)
{
char *p;
@@ -1260,8 +1272,8 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
*size = IVAL(cli->inbuf, smb_vwv3);
}
- if (t) {
- *t = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
+ if (write_time) {
+ *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
}
if (attr) {
@@ -1277,7 +1289,9 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
****************************************************************************/
BOOL cli_setattrE(struct cli_state *cli, int fd,
- time_t c_time, time_t a_time, time_t m_time)
+ time_t change_time,
+ time_t access_time,
+ time_t write_time)
{
char *p;
@@ -1292,9 +1306,9 @@ BOOL cli_setattrE(struct cli_state *cli, int fd,
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0, fd);
- cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, c_time);
- cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, a_time);
- cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, m_time);
+ cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
+ cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
+ cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
p = smb_buf(cli->outbuf);
*p++ = 4;
@@ -1367,7 +1381,7 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path)
memset(cli->outbuf,'\0',smb_size);
set_message(cli->outbuf,0,0,True);
- SCVAL(cli->outbuf,smb_com,SMBchkpth);
+ SCVAL(cli->outbuf,smb_com,SMBcheckpath);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
p = smb_buf(cli->outbuf);
@@ -1509,7 +1523,7 @@ static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigne
if (ea_namelen == 0 && ea_len == 0) {
data_len = 4;
- data = SMB_MALLOC(data_len);
+ data = (char *)SMB_MALLOC(data_len);
if (!data) {
return False;
}
@@ -1517,7 +1531,7 @@ static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigne
SIVAL(p,0,data_len);
} else {
data_len = 4 + 4 + ea_namelen + 1 + ea_len;
- data = SMB_MALLOC(data_len);
+ data = (char *)SMB_MALLOC(data_len);
if (!data) {
return False;
}
diff --git a/source/libsmb/clifsinfo.c b/source/libsmb/clifsinfo.c
index 2874ee6ca1c..9c3b6e3aed3 100644
--- a/source/libsmb/clifsinfo.c
+++ b/source/libsmb/clifsinfo.c
@@ -79,6 +79,59 @@ cleanup:
return ret;
}
+/****************************************************************************
+ Set UNIX extensions capabilities.
+****************************************************************************/
+
+BOOL cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor,
+ uint32 caplow, uint32 caphigh)
+{
+ BOOL ret = False;
+ uint16 setup;
+ char param[4];
+ char data[12];
+ char *rparam=NULL, *rdata=NULL;
+ unsigned int rparam_count=0, rdata_count=0;
+
+ setup = TRANSACT2_SETFSINFO;
+
+ SSVAL(param,0,0);
+ SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO);
+
+ SSVAL(data,0,major);
+ SSVAL(data,2,minor);
+ SIVAL(data,4,caplow);
+ SIVAL(data,8,caphigh);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL,
+ 0, 0,
+ &setup, 1, 0,
+ param, 4, 0,
+ data, 12, 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;
+ }
+
+cleanup:
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+
+ return ret;
+}
+
BOOL cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr)
{
BOOL ret = False;
@@ -229,7 +282,9 @@ BOOL cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *
}
if (pdate) {
- *pdate = interpret_long_date(rdata);
+ struct timespec ts;
+ ts = interpret_long_date(rdata);
+ *pdate = ts.tv_sec;
}
if (pserial_number) {
*pserial_number = IVAL(rdata,8);
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index fc9dd690b3f..f06a19b345c 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -130,12 +130,34 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
}
#endif
-#if defined(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES) && !defined(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES)
+#if !defined(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES)
+
+#if defined(HAVE_KRB5_SET_DEFAULT_TGS_ENCTYPES)
+
+/* With MIT kerberos, we should use krb5_set_default_tgs_enctypes in preference
+ * to krb5_set_default_tgs_ktypes. See
+ * http://lists.samba.org/archive/samba-technical/2006-July/048271.html
+ *
+ * If the MIT libraries are not exporting internal symbols, we will end up in
+ * this branch, which is correct. Otherwise we will continue to use the
+ * internal symbol
+ */
+ krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype *enc)
+{
+ return krb5_set_default_tgs_enctypes(ctx, enc);
+}
+
+#elif defined(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES)
+
+/* Heimdal */
krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype *enc)
{
return krb5_set_default_in_tkt_etypes(ctx, enc);
}
-#endif
+
+#endif /* HAVE_KRB5_SET_DEFAULT_TGS_ENCTYPES */
+
+#endif /* HAVE_KRB5_SET_DEFAULT_TGS_KTYPES */
#if defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS)
/* HEIMDAL */
@@ -194,7 +216,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
return ret;
}
- ret = krb5_string_to_key_salt(context, enctype, password->data, salt, key);
+ ret = krb5_string_to_key_salt(context, enctype, (const char *)password->data, salt, key);
krb5_free_salt(context, salt);
return ret;
}
@@ -239,18 +261,6 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
#error UNKNOWN_GET_ENCTYPES_FUNCTIONS
#endif
- void free_kerberos_etypes(krb5_context context,
- krb5_enctype *enctypes)
-{
-#if defined(HAVE_KRB5_FREE_KTYPES)
- krb5_free_ktypes(context, enctypes);
- return;
-#else
- SAFE_FREE(enctypes);
- return;
-#endif
-}
-
#if defined(HAVE_KRB5_AUTH_CON_SETKEY) && !defined(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY)
krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context,
krb5_auth_context auth_context,
@@ -373,6 +383,14 @@ BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_
}
#if !defined(HAVE_KRB5_LOCATE_KDC)
+
+/* krb5_locate_kdc is an internal MIT symbol. MIT are not yet willing to commit
+ * to a public interface for this functionality, so we have to be able to live
+ * without it if the MIT libraries are hiding their internal symbols.
+ */
+
+#if defined(KRB5_KRBHST_INIT)
+/* Heimdal */
krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters)
{
krb5_krbhst_handle hnd;
@@ -431,7 +449,19 @@ BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_
*addr_pp = sa;
return 0;
}
-#endif
+
+#else /* ! defined(KRB5_KRBHST_INIT) */
+
+ krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm,
+ struct sockaddr **addr_pp, int *naddrs, int get_masters)
+{
+ DEBUG(0, ("unable to explicitly locate the KDC on this platform\n"));
+ return KRB5_KDC_UNREACH;
+}
+
+#endif /* KRB5_KRBHST_INIT */
+
+#endif /* HAVE_KRB5_LOCATE_KDC */
#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME)
void krb5_free_unparsed_name(krb5_context context, char *val)
@@ -521,7 +551,8 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
const krb5_flags ap_req_options,
const char *principal,
krb5_ccache ccache,
- krb5_data *outbuf)
+ krb5_data *outbuf,
+ time_t *expire_time)
{
krb5_error_code retval;
krb5_principal server;
@@ -554,6 +585,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
}
while (!creds_ready && (i < maxtries)) {
+
if ((retval = krb5_get_credentials(context, 0, ccache,
&creds, &credsp))) {
DEBUG(1,("ads_krb5_mk_req: krb5_get_credentials failed for %s (%s)\n",
@@ -569,8 +601,9 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
krb5_set_real_time(context, t + time_offset + 1, 0);
}
- if (!ads_cleanup_expired_creds(context, ccache, credsp))
+ if (!ads_cleanup_expired_creds(context, ccache, credsp)) {
creds_ready = True;
+ }
i++;
}
@@ -580,6 +613,10 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
http_timestring((unsigned)credsp->times.endtime),
(unsigned)credsp->times.endtime));
+ if (expire_time) {
+ *expire_time = (time_t)credsp->times.endtime;
+ }
+
in_data.length = 0;
retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
&in_data, credsp, outbuf);
@@ -604,7 +641,9 @@ cleanup_princ:
*/
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
- uint32 extra_ap_opts, const char *ccname)
+ uint32 extra_ap_opts, const char *ccname,
+ time_t *tgs_expire)
+
{
krb5_error_code retval;
krb5_data packet;
@@ -648,7 +687,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
&auth_context,
AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
principal,
- ccdef, &packet))) {
+ ccdef, &packet,
+ tgs_expire))) {
goto failed;
}
@@ -705,7 +745,7 @@ failed:
static krb5_data kdata;
kdata.data = (char *)krb5_principal_get_comp_string(context, principal, i);
- kdata.length = strlen(kdata.data);
+ kdata.length = strlen((const char *)kdata.data);
return &kdata;
}
#endif
@@ -822,6 +862,7 @@ failed:
#endif
}
+#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */
static int get_kvno_from_ap_req(krb5_ap_req *ap_req)
{
#ifdef HAVE_TICKET_POINTER_IN_KRB5_AP_REQ /* MIT */
@@ -842,6 +883,7 @@ static krb5_enctype get_enctype_from_ap_req(krb5_ap_req *ap_req)
return ap_req->ticket->enc_part.enctype;
#endif
}
+#endif /* HAVE_KRB5_DECODE_AP_REQ */
static krb5_error_code
get_key_from_keytab(krb5_context context,
@@ -906,31 +948,16 @@ out:
return ret;
}
- void smb_krb5_free_ap_req(krb5_context context,
- krb5_ap_req *ap_req)
-{
-#ifdef HAVE_KRB5_FREE_AP_REQ /* MIT */
- krb5_free_ap_req(context, ap_req);
-#elif defined(HAVE_FREE_AP_REQ) /* Heimdal */
- free_AP_REQ(ap_req);
-#else
-#error UNKNOWN_KRB5_AP_REQ_FREE_FUNCTION
-#endif
-}
-
/* Prototypes */
-#if defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */
-krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
-#endif
krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context,
const krb5_data *inbuf,
krb5_kvno *kvno,
krb5_enctype *enctype)
{
- krb5_error_code ret;
#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */
{
+ krb5_error_code ret;
krb5_ap_req ap_req;
ret = krb5_decode_ap_req(context, inbuf, &ap_req);
@@ -940,25 +967,13 @@ krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
*kvno = get_kvno_from_ap_req(&ap_req);
*enctype = get_enctype_from_ap_req(&ap_req);
- smb_krb5_free_ap_req(context, &ap_req);
- }
-#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */
- {
- krb5_ap_req *ap_req = NULL;
-
- ret = decode_krb5_ap_req(inbuf, &ap_req);
- if (ret)
- return ret;
-
- *kvno = get_kvno_from_ap_req(ap_req);
- *enctype = get_enctype_from_ap_req(ap_req);
-
- smb_krb5_free_ap_req(context, ap_req);
+ free_AP_REQ(&ap_req);
+ return 0;
}
-#else
-#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION
#endif
- return ret;
+
+ /* Possibly not an appropriate error code. */
+ return KRB5KDC_ERR_BADOPTION;
}
krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context,
@@ -986,10 +1001,15 @@ krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
return ret;
}
+#ifdef KRB5_TICKET_HAS_KEYINFO
+ enctype = (*ticket)->enc_part.enctype;
+ kvno = (*ticket)->enc_part.kvno;
+#else
ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype);
if (ret) {
return ret;
}
+#endif
ret = get_key_from_keytab(context,
server,
@@ -1369,11 +1389,37 @@ done:
return ret;
}
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+ krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt)
+{
+ krb5_get_init_creds_opt *my_opt;
+
+ *opt = NULL;
+
+ if ((my_opt = SMB_MALLOC(sizeof(krb5_get_init_creds_opt))) == NULL) {
+ return ENOMEM;
+ }
+
+ krb5_get_init_creds_opt_init(my_opt);
+
+ *opt = my_opt;
+ return 0;
+}
+#endif
+
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE
+ void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
+{
+ SAFE_FREE(opt);
+ opt = NULL;
+}
+#endif
+
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
- const char *ccname)
+ const char *ccname, time_t *tgs_expire)
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return 1;
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 536bed5f787..22cb5930c26 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -49,9 +49,9 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
case 1: /* OS/2 understands this */
/* these dates are converted to GMT by
make_unix_date */
- finfo->ctime = cli_make_unix_date2(cli, p+4);
- finfo->atime = cli_make_unix_date2(cli, p+8);
- finfo->mtime = cli_make_unix_date2(cli, p+12);
+ finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4));
+ finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8));
+ finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12));
finfo->size = IVAL(p,16);
finfo->mode = CVAL(p,24);
len = CVAL(p, 26);
@@ -70,9 +70,9 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
case 2: /* this is what OS/2 uses mostly */
/* these dates are converted to GMT by
make_unix_date */
- finfo->ctime = cli_make_unix_date2(cli, p+4);
- finfo->atime = cli_make_unix_date2(cli, p+8);
- finfo->mtime = cli_make_unix_date2(cli, p+12);
+ finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4));
+ finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8));
+ finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12));
finfo->size = IVAL(p,16);
finfo->mode = CVAL(p,24);
len = CVAL(p, 30);
@@ -96,11 +96,11 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
/* Offset zero is "create time", not "change time". */
p += 8;
- finfo->atime = interpret_long_date(p);
+ finfo->atime_ts = interpret_long_date(p);
p += 8;
- finfo->mtime = interpret_long_date(p);
+ finfo->mtime_ts = interpret_long_date(p);
p += 8;
- finfo->ctime = interpret_long_date(p);
+ finfo->ctime_ts = interpret_long_date(p);
p += 8;
finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
p += 8;
@@ -321,7 +321,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
/* grab the data for later use */
/* and add them to the dirlist pool */
- dirlist = SMB_REALLOC(dirlist,dirlist_len + data_len);
+ dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
if (!dirlist) {
DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
@@ -349,10 +349,17 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
mnt = cli_cm_get_mntpoint( cli );
- for (p=dirlist,i=0;i<total_received;i++) {
- p += interpret_long_filename(cli,info_level,p,&finfo,NULL,NULL,NULL);
- fn( mnt,&finfo, Mask, state );
- }
+ /* see if the server disconnected or the connection otherwise failed */
+ if (cli_is_error(cli)) {
+ total_received = -1;
+ } else {
+ /* no connection problem. let user function add each entry */
+ for (p=dirlist,i=0;i<total_received;i++) {
+ p += interpret_long_filename(cli, info_level, p,
+ &finfo,NULL,NULL,NULL);
+ fn( mnt,&finfo, Mask, state );
+ }
+ }
/* free up the dirlist buffer and last name raw blob */
SAFE_FREE(dirlist);
@@ -373,8 +380,10 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
finfo->mode = CVAL(p,21);
/* this date is converted to GMT by make_unix_date */
- finfo->ctime = cli_make_unix_date(cli, p+22);
- finfo->mtime = finfo->atime = finfo->ctime;
+ finfo->ctime_ts.tv_sec = cli_make_unix_date(cli, p+22);
+ finfo->ctime_ts.tv_nsec = 0;
+ finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec;
+ finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0;
finfo->size = IVAL(p,26);
clistr_pull(cli, finfo->name, p+30, sizeof(finfo->name), 12, STR_ASCII);
if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) {
@@ -447,7 +456,8 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
first = False;
- dirlist = SMB_REALLOC(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
+ dirlist = (char *)SMB_REALLOC(
+ dirlist,(num_received + received)*DIR_STRUCT_SIZE);
if (!dirlist) {
DEBUG(0,("cli_list_old: failed to expand dirlist"));
return 0;
diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c
index 2be4da8f7fd..61cdd79f36b 100644
--- a/source/libsmb/clirap.c
+++ b/source/libsmb/clirap.c
@@ -244,7 +244,8 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
)) {
int res = rparam? SVAL(rparam,0) : -1;
- if (res == 0 || res == ERRmoredata) {
+ if (res == 0 || res == ERRmoredata ||
+ (res != -1 && cli_errno(cli) == 0)) {
int i;
int converter=SVAL(rparam,2);
@@ -379,7 +380,9 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
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,
+ time_t *change_time,
+ time_t *access_time,
+ time_t *write_time,
SMB_OFF_T *size, uint16 *mode)
{
unsigned int data_len = 0;
@@ -434,14 +437,14 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
date_fn = cli_make_unix_date2;
}
- if (c_time) {
- *c_time = date_fn(cli, rdata+0);
+ if (change_time) {
+ *change_time = date_fn(cli, rdata+0);
}
- if (a_time) {
- *a_time = date_fn(cli, rdata+4);
+ if (access_time) {
+ *access_time = date_fn(cli, rdata+4);
}
- if (m_time) {
- *m_time = date_fn(cli, rdata+8);
+ if (write_time) {
+ *write_time = date_fn(cli, rdata+8);
}
if (size) {
*size = IVAL(rdata, 12);
@@ -460,7 +463,11 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
send a setpathinfo call
****************************************************************************/
BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
- time_t c_time, time_t a_time, time_t m_time, uint16 mode)
+ time_t create_time,
+ time_t access_time,
+ time_t write_time,
+ time_t change_time,
+ uint16 mode)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
@@ -495,16 +502,16 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
* Add the create, last access, modification, and status change times
*/
- /* Don't set create time, at offset 0 */
+ put_long_date(p, create_time);
p += 8;
- put_long_date(p, a_time);
+ put_long_date(p, access_time);
p += 8;
- put_long_date(p, m_time);
+ put_long_date(p, write_time);
p += 8;
- put_long_date(p, c_time);
+ put_long_date(p, change_time);
p += 8;
/* Add attributes */
@@ -555,8 +562,11 @@ 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 *create_time, time_t *access_time, time_t *write_time,
- time_t *change_time, SMB_OFF_T *size, uint16 *mode,
+ struct timespec *create_time,
+ struct timespec *access_time,
+ struct timespec *write_time,
+ struct timespec *change_time,
+ SMB_OFF_T *size, uint16 *mode,
SMB_INO_T *ino)
{
unsigned int data_len = 0;
@@ -670,8 +680,11 @@ send a qfileinfo call
****************************************************************************/
BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
uint16 *mode, SMB_OFF_T *size,
- time_t *create_time, time_t *access_time, time_t *write_time,
- time_t *change_time, SMB_INO_T *ino)
+ struct timespec *create_time,
+ struct timespec *access_time,
+ struct timespec *write_time,
+ struct timespec *change_time,
+ SMB_INO_T *ino)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
@@ -794,9 +807,9 @@ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
return False;
}
- sbuf->st_atime = interpret_long_date( rdata+8 ); /* Access time. */
- sbuf->st_mtime = interpret_long_date( rdata+16 ); /* Write time. */
- sbuf->st_ctime = interpret_long_date( rdata+24 ); /* Change time. */
+ set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
+ set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
+ set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
*attributes = IVAL( rdata, 32 );
@@ -848,7 +861,13 @@ BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutd
return False;
}
- *poutdata = memdup(rdata, data_len);
+ *poutdata = (char *)memdup(rdata, data_len);
+ if (!*poutdata) {
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return False;
+ }
+
*poutlen = data_len;
SAFE_FREE(rdata);
diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c
index 147683689d6..d6a44f4ea22 100644
--- a/source/libsmb/clirap2.c
+++ b/source/libsmb/clirap2.c
@@ -220,7 +220,7 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
/* Allocate data. */
data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
- data = SMB_MALLOC(data_size);
+ data = SMB_MALLOC_ARRAY(char, data_size);
if (!data) {
DEBUG (1, ("Malloc fail\n"));
return -1;
@@ -1414,6 +1414,62 @@ BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
return(res == 0 || res == ERRmoredata);
}
+BOOL cli_get_server_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ char **servername)
+{
+ char *rparam = NULL;
+ char *rdata = NULL;
+ unsigned int rdrcnt,rprcnt;
+ char *p;
+ char param[WORDSIZE /* api number */
+ +sizeof(RAP_WserverGetInfo_REQ) /* req string */
+ +sizeof(RAP_SERVER_INFO_L1) /* return string */
+ +WORDSIZE /* info level */
+ +WORDSIZE]; /* buffer size */
+ BOOL res = False;
+ fstring tmp;
+
+ /* send a SMBtrans command with api NetServerGetInfo */
+ p = make_header(param, RAP_WserverGetInfo,
+ RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
+ PUTWORD(p, 1); /* info level */
+ PUTWORD(p, CLI_BUFFER_SIZE);
+
+ if (!cli_api(cli,
+ param, PTR_DIFF(p,param), 8, /* params, length, max */
+ NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
+ &rparam, &rprcnt, /* return params, return size */
+ &rdata, &rdrcnt /* return data, return size */
+ )) {
+ goto failed;
+ }
+
+ if (GETRES(rparam) != 0) {
+ goto failed;
+ }
+
+ if (rdrcnt < 16) {
+ DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt));
+ goto failed;
+ }
+
+ if (pull_ascii(tmp, rdata, sizeof(tmp)-1, 16, STR_TERMINATE) == -1) {
+ DEBUG(10, ("pull_ascii failed\n"));
+ goto failed;
+ }
+
+ if (!(*servername = talloc_strdup(mem_ctx, tmp))) {
+ DEBUG(1, ("talloc_strdup failed\n"));
+ goto failed;
+ }
+
+ res = True;
+
+ failed:
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+ return res;
+}
/*************************************************************************
*
diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c
index 883bc1260d6..02fa804f41f 100644
--- a/source/libsmb/clireadwrite.c
+++ b/source/libsmb/clireadwrite.c
@@ -265,11 +265,11 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset,
BOOL large_writex = False;
if (size > cli->bufsize) {
- cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024);
+ cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024);
if (!cli->outbuf) {
return False;
}
- cli->inbuf = SMB_REALLOC(cli->inbuf, size + 1024);
+ cli->inbuf = (char *)SMB_REALLOC(cli->inbuf, size + 1024);
if (cli->inbuf == NULL) {
SAFE_FREE(cli->outbuf);
return False;
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index a01c009b6e3..6aca217e259 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -343,7 +343,8 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
*/
int spnego_gen_negTokenTarg(const char *principal, int time_offset,
DATA_BLOB *targ,
- DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
+ DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
+ time_t *expire_time)
{
int retval;
DATA_BLOB tkt, tkt_wrapped;
@@ -351,7 +352,8 @@ int spnego_gen_negTokenTarg(const char *principal, int time_offset,
/* get a kerberos ticket for the service and extract the session key */
retval = cli_krb5_get_ticket(principal, time_offset,
- &tkt, session_key_krb5, extra_ap_opts, NULL);
+ &tkt, session_key_krb5, extra_ap_opts, NULL,
+ expire_time);
if (retval)
return retval;
diff --git a/source/libsmb/clistr.c b/source/libsmb/clistr.c
index c61445c0735..6191f99ea96 100644
--- a/source/libsmb/clistr.c
+++ b/source/libsmb/clistr.c
@@ -49,10 +49,10 @@ size_t clistr_pull_fn(const char *function, unsigned int line,
size_t clistr_align_out(struct cli_state *cli, const void *p, int flags)
{
- return align_string(cli->outbuf, p, flags);
+ return align_string(cli->outbuf, (const char *)p, flags);
}
size_t clistr_align_in(struct cli_state *cli, const void *p, int flags)
{
- return align_string(cli->inbuf, p, flags);
+ return align_string(cli->inbuf, (const char *)p, flags);
}
diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c
index 4f9f21b8483..27207e72e2f 100644
--- a/source/libsmb/clitrans.c
+++ b/source/libsmb/clitrans.c
@@ -207,7 +207,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
/* allocate it */
if (total_data!=0) {
- *data = SMB_REALLOC(*data,total_data);
+ *data = (char *)SMB_REALLOC(*data,total_data);
if (!(*data)) {
DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
goto out;
@@ -215,7 +215,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
}
if (total_param!=0) {
- *param = SMB_REALLOC(*param,total_param);
+ *param = (char *)SMB_REALLOC(*param,total_param);
if (!(*param)) {
DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
goto out;
@@ -511,7 +511,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
/* allocate it */
if (total_data) {
- *data = SMB_REALLOC(*data,total_data);
+ *data = (char *)SMB_REALLOC(*data,total_data);
if (!(*data)) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
goto out;
@@ -519,7 +519,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
}
if (total_param) {
- *param = SMB_REALLOC(*param,total_param);
+ *param = (char *)SMB_REALLOC(*param,total_param);
if (!(*param)) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
goto out;
diff --git a/source/libsmb/conncache.c b/source/libsmb/conncache.c
index 49512d7a2e5..b8ddcb2ba91 100644
--- a/source/libsmb/conncache.c
+++ b/source/libsmb/conncache.c
@@ -162,3 +162,31 @@ void flush_negative_conn_cache( void )
}
}
+
+/****************************************************************************
+ Remove all negative entries for a domain. Used when going to online state in
+ winbindd.
+****************************************************************************/
+
+void flush_negative_conn_cache_for_domain(const char *domain)
+{
+ struct failed_connection_cache *fcc;
+
+ fcc = failed_connection_cache;
+
+ while (fcc) {
+ struct failed_connection_cache *fcc_next;
+
+ fcc_next = fcc->next;
+
+ if (strequal(fcc->domain_name, domain)) {
+ DEBUG(10,("flush_negative_conn_cache_for_domain: removed server %s "
+ " from failed cache for domain %s\n",
+ fcc->controller, domain));
+ DLIST_REMOVE(failed_connection_cache, fcc);
+ free(fcc);
+ }
+
+ fcc = fcc_next;
+ }
+}
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index b3caa0a80ce..6745c0e23a3 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -1511,6 +1511,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ EACCES, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
{ ENOENT, ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND },
{ ENOTDIR, ERRDOS, ERRbadpath, NT_STATUS_NOT_A_DIRECTORY },
+ { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
{ EIO, ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
{ EBADF, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
{ EINVAL, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
@@ -1522,7 +1523,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ EISDIR, ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY},
{ EMLINK, ERRDOS, ERRgeneral, NT_STATUS_TOO_MANY_LINKS },
#ifdef EDQUOT
- { EDQUOT, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
+ { EDQUOT, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL }, /* Windows apps need this, not NT_STATUS_QUOTA_EXCEEDED */
#endif
#ifdef ENOTEMPTY
{ ENOTEMPTY, ERRDOS, ERRnoaccess, NT_STATUS_DIRECTORY_NOT_EMPTY },
@@ -1533,12 +1534,12 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
#ifdef EROFS
{ EROFS, ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
#endif
-#ifdef ENAMETOOLONG
- { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
-#endif
#ifdef EFBIG
{ EFBIG, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
#endif
+#ifdef ENOBUFS
+ { ENOBUFS, ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES },
+#endif
{ 0, 0, 0, NT_STATUS_OK }
};
diff --git a/source/libsmb/gpo.c b/source/libsmb/gpo.c
deleted file mode 100644
index 0257138ece2..00000000000
--- a/source/libsmb/gpo.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Group Policy Object Support
- * Copyright (C) Guenther Deschner 2005
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-
-#define GPT_INI_SECTION_GENERAL "General"
-#define GPT_INI_PARAMETER_VERSION "Version"
-#define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
-
-struct gpt_ini {
- uint32 version;
- const char *display_name;
-};
-
-static uint32 version;
-
-static BOOL do_section(const char *section)
-{
- DEBUG(10,("do_section: %s\n", section));
-
- return True;
-}
-
-static BOOL do_parameter(const char *parameter, const char *value)
-{
- DEBUG(10,("do_parameter: %s, %s\n", parameter, value));
-
- if (strequal(parameter, GPT_INI_PARAMETER_VERSION)) {
- version = atoi(value);
- }
- return True;
-}
-
-NTSTATUS ads_gpo_get_sysvol_gpt_version(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- const char *filesyspath,
- uint32 *sysvol_version)
-{
- NTSTATUS status;
- const char *path;
- struct cli_state *cli;
- int fnum;
- fstring tok;
- static int io_bufsize = 64512;
- int read_size = io_bufsize;
- char *data = NULL;
- off_t start = 0;
- off_t nread = 0;
- int handle = 0;
- const char *local_file;
-
- *sysvol_version = 0;
-
- next_token(&filesyspath, tok, "\\", sizeof(tok));
- next_token(&filesyspath, tok, "\\", sizeof(tok));
-
- path = talloc_asprintf(mem_ctx, "\\%s\\gpt.ini", filesyspath);
- if (path == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- local_file = talloc_asprintf(mem_ctx, "%s/%s", lock_path("gpo_cache"), "gpt.ini");
- if (local_file == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* FIXME: walk down the dfs tree instead */
- status = cli_full_connection(&cli, global_myname(),
- ads->config.ldap_server_name,
- NULL, 0,
- "SYSVOL", "A:",
- ads->auth.user_name, NULL, ads->auth.password,
- CLI_FULL_CONNECTION_USE_KERBEROS,
- Undefined, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- fnum = cli_open(cli, path, O_RDONLY, DENY_NONE);
- if (fnum == -1) {
- return NT_STATUS_NO_SUCH_FILE;
- }
-
-
- data = (char *)SMB_MALLOC(read_size);
- if (data == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- handle = sys_open(local_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-
- if (handle == -1) {
- return NT_STATUS_NO_SUCH_FILE;
- }
-
- while (1) {
-
- int n = cli_read(cli, fnum, data, nread + start, read_size);
-
- if (n <= 0)
- break;
-
- if (write(handle, data, n) != n) {
- break;
- }
-
- nread += n;
- }
-
- cli_close(cli, fnum);
-
- if (!pm_process(local_file, do_section, do_parameter)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- *sysvol_version = version;
-
- SAFE_FREE(data);
-
- cli_shutdown(cli);
-
- return NT_STATUS_OK;
-}
-
-/*
-
-perfectly parseable with pm_process() :))
-
-[Unicode]
-Unicode=yes
-[System Access]
-MinimumPasswordAge = 1
-MaximumPasswordAge = 42
-MinimumPasswordLength = 7
-PasswordComplexity = 1
-PasswordHistorySize = 24
-LockoutBadCount = 0
-RequireLogonToChangePassword = 0
-ForceLogoffWhenHourExpire = 0
-ClearTextPassword = 0
-[Kerberos Policy]
-MaxTicketAge = 10
-MaxRenewAge = 7
-MaxServiceAge = 600
-MaxClockSkew = 5
-TicketValidateClient = 1
-[Version]
-signature="$CHICAGO$"
-Revision=1
-*/
diff --git a/source/libsmb/libsmb_cache.c b/source/libsmb/libsmb_cache.c
index 5d948ea5e25..fdde7acaf86 100644
--- a/source/libsmb/libsmb_cache.c
+++ b/source/libsmb/libsmb_cache.c
@@ -26,6 +26,9 @@
#include "include/libsmbclient.h"
#include "../include/libsmb_internal.h"
+
+int smbc_default_cache_functions(SMBCCTX * context);
+
/*
* Structure we use if internal caching mechanism is used
* nothing fancy here.
@@ -150,9 +153,10 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
* doesn't match the requested share, so
* disconnect from the current share.
*/
- if (! cli_tdis(&srv->server->cli)) {
+ if (! cli_tdis(srv->server->cli)) {
/* Sigh. Couldn't disconnect. */
- cli_shutdown(&srv->server->cli);
+ cli_shutdown(srv->server->cli);
+ srv->server->cli = NULL;
context->callbacks.remove_cached_srv_fn(context, srv->server);
continue;
}
@@ -166,7 +170,8 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
srv->share_name = SMB_STRDUP(share);
if (!srv->share_name) {
/* Out of memory. */
- cli_shutdown(&srv->server->cli);
+ cli_shutdown(srv->server->cli);
+ srv->server->cli = NULL;
context->callbacks.remove_cached_srv_fn(context, srv->server);
continue;
}
diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index 80b09fab1a1..6a154aa68e2 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/libsmb/libsmbclient.c
@@ -26,6 +26,9 @@
#include "include/libsmb_internal.h"
+struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir);
+struct smbc_dir_list *smbc_check_dir_ent(struct smbc_dir_list *list,
+ struct smbc_dirent *dirent);
/*
* DOS Attribute values (used internally)
@@ -33,9 +36,10 @@
typedef struct DOS_ATTR_DESC {
int mode;
SMB_OFF_T size;
- time_t a_time;
- time_t c_time;
- time_t m_time;
+ time_t create_time;
+ time_t access_time;
+ time_t write_time;
+ time_t change_time;
SMB_INO_T inode;
} DOS_ATTR_DESC;
@@ -236,7 +240,7 @@ smbc_urlencode(char * dest, char * src, int max_dest_len)
*
*
* We accept:
- * smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]][?options]
+ * smb://[[[domain;]user[:password]@]server[/share[/path[/file]]]][?options]
*
* Meaning of URLs:
*
@@ -359,19 +363,19 @@ smbc_parse_path(SMBCCTX *context,
pstring username, passwd, domain;
const char *u = userinfo;
- next_token(&p, userinfo, "@", sizeof(fstring));
+ next_token_no_ltrim(&p, userinfo, "@", sizeof(fstring));
username[0] = passwd[0] = domain[0] = 0;
if (strchr_m(u, ';')) {
- next_token(&u, domain, ";", sizeof(fstring));
+ next_token_no_ltrim(&u, domain, ";", sizeof(fstring));
}
if (strchr_m(u, ':')) {
- next_token(&u, username, ":", sizeof(fstring));
+ next_token_no_ltrim(&u, username, ":", sizeof(fstring));
pstrcpy(passwd, u);
@@ -495,7 +499,7 @@ static int
smbc_check_server(SMBCCTX * context,
SMBCSRV * server)
{
- if ( send_keepalive(server->cli.fd) == False )
+ if ( send_keepalive(server->cli->fd) == False )
return 1;
/* connection is ok */
@@ -532,7 +536,8 @@ smbc_remove_unused_server(SMBCCTX * context,
DLIST_REMOVE(context->internal->_servers, srv);
- cli_shutdown(&srv->cli);
+ cli_shutdown(srv->cli);
+ srv->cli = NULL;
DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
@@ -638,7 +643,7 @@ smbc_server(SMBCCTX *context,
fstring password)
{
SMBCSRV *srv=NULL;
- struct cli_state c;
+ struct cli_state *c;
struct nmb_name called, calling;
const char *server_n = server;
pstring ipenv;
@@ -674,7 +679,7 @@ smbc_server(SMBCCTX *context,
* disconnect if the requested share is not the same as the
* one that was already connected.
*/
- if (srv->cli.cnum == (uint16) -1) {
+ if (srv->cli->cnum == (uint16) -1) {
/* Ensure we have accurate auth info */
if (context->internal->_auth_fn_with_context != NULL) {
context->internal->_auth_fn_with_context(
@@ -691,11 +696,12 @@ smbc_server(SMBCCTX *context,
password, sizeof(fstring));
}
- if (! cli_send_tconX(&srv->cli, share, "?????",
+ if (! cli_send_tconX(srv->cli, share, "?????",
password, strlen(password)+1)) {
- errno = smbc_errno(context, &srv->cli);
- cli_shutdown(&srv->cli);
+ errno = smbc_errno(context, srv->cli);
+ cli_shutdown(srv->cli);
+ srv->cli = NULL;
context->callbacks.remove_cached_srv_fn(context,
srv);
srv = NULL;
@@ -738,19 +744,19 @@ smbc_server(SMBCCTX *context,
zero_ip(&ip);
/* have to open a new connection */
- if (!cli_initialise(&c)) {
+ if ((c = cli_initialise()) == NULL) {
errno = ENOMEM;
return NULL;
}
if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) {
- c.use_kerberos = True;
+ c->use_kerberos = True;
}
if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) {
- c.fallback_after_kerberos = True;
+ c->fallback_after_kerberos = True;
}
- c.timeout = context->timeout;
+ c->timeout = context->timeout;
/*
* Force use of port 139 for first try if share is $IPC, empty, or
@@ -764,49 +770,47 @@ smbc_server(SMBCCTX *context,
port_try_next = 139;
}
- c.port = port_try_first;
+ c->port = port_try_first;
- if (!cli_connect(&c, server_n, &ip)) {
+ if (!cli_connect(c, server_n, &ip)) {
/* First connection attempt failed. Try alternate port. */
- c.port = port_try_next;
+ c->port = port_try_next;
- if (!cli_connect(&c, server_n, &ip)) {
- cli_shutdown(&c);
+ if (!cli_connect(c, server_n, &ip)) {
+ cli_shutdown(c);
errno = ETIMEDOUT;
return NULL;
}
}
- if (!cli_session_request(&c, &calling, &called)) {
- cli_shutdown(&c);
+ if (!cli_session_request(c, &calling, &called)) {
+ cli_shutdown(c);
if (strcmp(called.name, "*SMBSERVER")) {
make_nmb_name(&called , "*SMBSERVER", 0x20);
goto again;
- }
- else { /* Try one more time, but ensure we don't loop */
-
- /* Only try this if server is an IP address ... */
-
- if (is_ipaddress(server) && !tried_reverse) {
- fstring remote_name;
- struct in_addr rem_ip;
+ } else { /* Try one more time, but ensure we don't loop */
- if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
- DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
- errno = ETIMEDOUT;
- return NULL;
- }
+ /* Only try this if server is an IP address ... */
- tried_reverse++; /* Yuck */
+ if (is_ipaddress(server) && !tried_reverse) {
+ fstring remote_name;
+ struct in_addr rem_ip;
- if (name_status_find("*", 0, 0, rem_ip, remote_name)) {
- make_nmb_name(&called, remote_name, 0x20);
- goto again;
- }
+ if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
+ DEBUG(4, ("Could not convert IP address "
+ "%s to struct in_addr\n", server));
+ errno = ETIMEDOUT;
+ return NULL;
+ }
+ tried_reverse++; /* Yuck */
- }
+ if (name_status_find("*", 0, 0, rem_ip, remote_name)) {
+ make_nmb_name(&called, remote_name, 0x20);
+ goto again;
+ }
+ }
}
errno = ETIMEDOUT;
return NULL;
@@ -814,29 +818,29 @@ smbc_server(SMBCCTX *context,
DEBUG(4,(" session request ok\n"));
- if (!cli_negprot(&c)) {
- cli_shutdown(&c);
+ if (!cli_negprot(c)) {
+ cli_shutdown(c);
errno = ETIMEDOUT;
return NULL;
}
username_used = username;
- if (!cli_session_setup(&c, username_used,
- password, strlen(password),
- password, strlen(password),
- workgroup)) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
+ password, strlen(password),
+ password, strlen(password),
+ 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)) {
+ !NT_STATUS_IS_OK(cli_session_setup(c, username_used,
+ password, 1,
+ password, 0,
+ workgroup))) {
- cli_shutdown(&c);
+ cli_shutdown(c);
errno = EPERM;
return NULL;
}
@@ -844,10 +848,10 @@ smbc_server(SMBCCTX *context,
DEBUG(4,(" session setup ok\n"));
- if (!cli_send_tconX(&c, share, "?????",
+ if (!cli_send_tconX(c, share, "?????",
password, strlen(password)+1)) {
- errno = smbc_errno(context, &c);
- cli_shutdown(&c);
+ errno = smbc_errno(context, c);
+ cli_shutdown(c);
return NULL;
}
@@ -866,7 +870,6 @@ smbc_server(SMBCCTX *context,
ZERO_STRUCTP(srv);
srv->cli = c;
- srv->cli.allocated = False;
srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
srv->no_pathinfo = False;
srv->no_pathinfo2 = False;
@@ -892,8 +895,10 @@ smbc_server(SMBCCTX *context,
return srv;
failed:
- cli_shutdown(&c);
- if (!srv) return NULL;
+ cli_shutdown(c);
+ if (!srv) {
+ return NULL;
+ }
SAFE_FREE(srv);
return NULL;
@@ -968,19 +973,16 @@ smbc_attr_server(SMBCCTX *context,
}
ZERO_STRUCTP(ipc_srv);
- ipc_srv->cli = *ipc_cli;
- ipc_srv->cli.allocated = False;
-
- free(ipc_cli);
+ ipc_srv->cli = ipc_cli;
if (pol) {
- pipe_hnd = cli_rpc_pipe_open_noauth(&ipc_srv->cli,
+ pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
PI_LSARPC,
&nt_status);
if (!pipe_hnd) {
DEBUG(1, ("cli_nt_session_open fail!\n"));
errno = ENOTSUP;
- cli_shutdown(&ipc_srv->cli);
+ cli_shutdown(ipc_srv->cli);
free(ipc_srv);
return NULL;
}
@@ -993,14 +995,14 @@ smbc_attr_server(SMBCCTX *context,
nt_status = rpccli_lsa_open_policy(
pipe_hnd,
- ipc_srv->cli.mem_ctx,
+ ipc_srv->cli->mem_ctx,
True,
GENERIC_EXECUTE_ACCESS,
pol);
if (!NT_STATUS_IS_OK(nt_status)) {
- errno = smbc_errno(context, &ipc_srv->cli);
- cli_shutdown(&ipc_srv->cli);
+ errno = smbc_errno(context, ipc_srv->cli);
+ cli_shutdown(ipc_srv->cli);
return NULL;
}
}
@@ -1017,7 +1019,7 @@ smbc_attr_server(SMBCCTX *context,
if (errno == 0) {
errno = ENOMEM;
}
- cli_shutdown(&ipc_srv->cli);
+ cli_shutdown(ipc_srv->cli);
free(ipc_srv);
return NULL;
}
@@ -1106,7 +1108,7 @@ smbc_open_ctx(SMBCCTX *context,
ZERO_STRUCTP(file);
/*d_printf(">>>open: resolving %s\n", path);*/
- if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath))
+ if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
SAFE_FREE(file);
@@ -1121,7 +1123,8 @@ smbc_open_ctx(SMBCCTX *context,
cli_dfs_make_full_path( targetpath, targetcli->desthost, targetcli->share, temppath);
}
- if ((fd = cli_open(targetcli, targetpath, flags, DENY_NONE)) < 0) {
+ if ((fd = cli_open(targetcli, targetpath, flags,
+ context->internal->_share_mode)) < 0) {
/* Handle the error ... */
@@ -1180,7 +1183,7 @@ smbc_open_ctx(SMBCCTX *context,
if (fd == -1) {
int eno = 0;
- eno = smbc_errno(context, &srv->cli);
+ eno = smbc_errno(context, srv->cli);
file = context->opendir(context, fname);
if (!file) errno = eno;
return file;
@@ -1283,7 +1286,7 @@ smbc_read_ctx(SMBCCTX *context,
}
/*d_printf(">>>read: resolving %s\n", path);*/
- if (!cli_resolve_path("", &file->srv->cli, path,
+ if (!cli_resolve_path("", file->srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -1291,7 +1294,7 @@ smbc_read_ctx(SMBCCTX *context,
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
- ret = cli_read(targetcli, file->cli_fd, buf, offset, count);
+ ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
if (ret < 0) {
@@ -1366,7 +1369,7 @@ smbc_write_ctx(SMBCCTX *context,
}
/*d_printf(">>>write: resolving %s\n", path);*/
- if (!cli_resolve_path("", &file->srv->cli, path,
+ if (!cli_resolve_path("", file->srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -1375,7 +1378,7 @@ smbc_write_ctx(SMBCCTX *context,
/*d_printf(">>>write: resolved path as %s\n", targetpath);*/
- ret = cli_write(targetcli, file->cli_fd, 0, buf, offset, count);
+ ret = cli_write(targetcli, file->cli_fd, 0, (char *)buf, offset, count);
if (ret <= 0) {
@@ -1438,7 +1441,7 @@ smbc_close_ctx(SMBCCTX *context,
}
/*d_printf(">>>close: resolving %s\n", path);*/
- if (!cli_resolve_path("", &file->srv->cli, path,
+ if (!cli_resolve_path("", file->srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -1480,14 +1483,16 @@ smbc_getatr(SMBCCTX * context,
char *path,
uint16 *mode,
SMB_OFF_T *size,
- time_t *c_time,
- time_t *a_time,
- time_t *m_time,
+ struct timespec *create_time_ts,
+ struct timespec *access_time_ts,
+ struct timespec *write_time_ts,
+ struct timespec *change_time_ts,
SMB_INO_T *ino)
{
pstring fixedpath;
pstring targetpath;
struct cli_state *targetcli;
+ time_t write_time;
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -1508,7 +1513,7 @@ smbc_getatr(SMBCCTX * context,
}
DEBUG(4,("smbc_getatr: sending qpathinfo\n"));
- if (!cli_resolve_path( "", &srv->cli, fixedpath, &targetcli, targetpath))
+ if (!cli_resolve_path( "", srv->cli, fixedpath, &targetcli, targetpath))
{
d_printf("Couldn't resolve %s\n", path);
return False;
@@ -1524,7 +1529,11 @@ smbc_getatr(SMBCCTX * context,
if (!srv->no_pathinfo2 &&
cli_qpathinfo2(targetcli, targetpath,
- NULL, a_time, m_time, c_time, size, mode, ino)) {
+ create_time_ts,
+ access_time_ts,
+ write_time_ts,
+ change_time_ts,
+ size, mode, ino)) {
return True;
}
@@ -1534,11 +1543,28 @@ smbc_getatr(SMBCCTX * context,
return False;
}
- if (cli_getatr(targetcli, targetpath, mode, size, m_time)) {
- if (m_time != NULL) {
- if (a_time != NULL) *a_time = *m_time;
- if (c_time != NULL) *c_time = *m_time;
+ if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) {
+
+ struct timespec w_time_ts;
+
+ w_time_ts = convert_time_t_to_timespec(write_time);
+
+ if (write_time_ts != NULL) {
+ *write_time_ts = w_time_ts;
+ }
+
+ if (create_time_ts != NULL) {
+ *create_time_ts = w_time_ts;
+ }
+
+ if (access_time_ts != NULL) {
+ *access_time_ts = w_time_ts;
+ }
+
+ if (change_time_ts != NULL) {
+ *change_time_ts = w_time_ts;
}
+
srv->no_pathinfo2 = True;
return True;
}
@@ -1560,7 +1586,10 @@ smbc_getatr(SMBCCTX * context,
*/
static BOOL
smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
- time_t c_time, time_t a_time, time_t m_time,
+ time_t create_time,
+ time_t access_time,
+ time_t write_time,
+ time_t change_time,
uint16 mode)
{
int fd;
@@ -1573,7 +1602,12 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
* attributes manipulated.
*/
if (srv->no_pathinfo ||
- ! cli_setpathinfo(&srv->cli, path, c_time, a_time, m_time, mode)) {
+ ! cli_setpathinfo(srv->cli, path,
+ create_time,
+ access_time,
+ write_time,
+ change_time,
+ mode)) {
/*
* setpathinfo is not supported; go to plan B.
@@ -1589,48 +1623,20 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
srv->no_pathinfo = True;
/* Open the file */
- if ((fd = cli_open(&srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
+ if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
return -1;
}
- /*
- * Get the creat time of the file (if it wasn't provided).
- * We'll need it in the set call
- */
- if (c_time == 0) {
- ret = cli_getattrE(&srv->cli, fd,
- NULL, NULL,
- &c_time, NULL, NULL);
- } else {
- ret = True;
- }
-
- /* If we got create time, set times */
- if (ret) {
- /* Some OS versions don't support create time */
- if (c_time == 0 || c_time == -1) {
- c_time = time(NULL);
- }
+ /* Set the new attributes */
+ ret = cli_setattrE(srv->cli, fd,
+ change_time,
+ access_time,
+ write_time);
- /*
- * For sanity sake, since there is no POSIX function
- * to set the create time of a file, if the existing
- * create time is greater than either of access time
- * or modification time, set create time to the
- * smallest of those. This ensure that the create
- * time of a file is never greater than its last
- * access or modification time.
- */
- if (c_time > a_time) c_time = a_time;
- if (c_time > m_time) c_time = m_time;
-
- /* Set the new attributes */
- ret = cli_setattrE(&srv->cli, fd,
- c_time, a_time, m_time);
- cli_close(&srv->cli, fd);
- }
+ /* Close the file */
+ cli_close(srv->cli, fd);
/*
* Unfortunately, setattrE() doesn't have a provision for
@@ -1639,11 +1645,11 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
* seems to work on win98.
*/
if (ret && mode != (uint16) -1) {
- ret = cli_setatr(&srv->cli, path, mode, 0);
+ ret = cli_setatr(srv->cli, path, mode, 0);
}
if (! ret) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
return False;
}
}
@@ -1703,7 +1709,7 @@ smbc_unlink_ctx(SMBCCTX *context,
}
/*d_printf(">>>unlink: resolving %s\n", path);*/
- if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath))
+ if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
return -1;
@@ -1719,11 +1725,17 @@ smbc_unlink_ctx(SMBCCTX *context,
int saverr = errno;
SMB_OFF_T size = 0;
uint16 mode = 0;
- time_t m_time = 0, a_time = 0, c_time = 0;
+ struct timespec write_time_ts;
+ struct timespec access_time_ts;
+ struct timespec change_time_ts;
SMB_INO_T ino = 0;
if (!smbc_getatr(context, srv, path, &mode, &size,
- &c_time, &a_time, &m_time, &ino)) {
+ NULL,
+ &access_time_ts,
+ &write_time_ts,
+ &change_time_ts,
+ &ino)) {
/* Hmmm, bad error ... What? */
@@ -1836,14 +1848,14 @@ smbc_rename_ctx(SMBCCTX *ocontext,
}
/*d_printf(">>>rename: resolving %s\n", path1);*/
- if (!cli_resolve_path( "", &srv->cli, path1, &targetcli1, targetpath1))
+ if (!cli_resolve_path( "", srv->cli, path1, &targetcli1, targetpath1))
{
d_printf("Could not resolve %s\n", path1);
return -1;
}
/*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/
/*d_printf(">>>rename: resolving %s\n", path2);*/
- if (!cli_resolve_path( "", &srv->cli, path2, &targetcli2, targetpath2))
+ if (!cli_resolve_path( "", srv->cli, path2, &targetcli2, targetpath2))
{
d_printf("Could not resolve %s\n", path2);
return -1;
@@ -1938,7 +1950,7 @@ smbc_lseek_ctx(SMBCCTX *context,
}
/*d_printf(">>>lseek: resolving %s\n", path);*/
- if (!cli_resolve_path("", &file->srv->cli, path,
+ if (!cli_resolve_path("", file->srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -2059,9 +2071,9 @@ smbc_stat_ctx(SMBCCTX *context,
fstring password;
fstring workgroup;
pstring path;
- time_t m_time = 0;
- time_t a_time = 0;
- time_t c_time = 0;
+ struct timespec write_time_ts;
+ struct timespec access_time_ts;
+ struct timespec change_time_ts;
SMB_OFF_T size = 0;
uint16 mode = 0;
SMB_INO_T ino = 0;
@@ -2105,9 +2117,13 @@ smbc_stat_ctx(SMBCCTX *context,
}
if (!smbc_getatr(context, srv, path, &mode, &size,
- &c_time, &a_time, &m_time, &ino)) {
+ NULL,
+ &access_time_ts,
+ &write_time_ts,
+ &change_time_ts,
+ &ino)) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
return -1;
}
@@ -2116,9 +2132,9 @@ smbc_stat_ctx(SMBCCTX *context,
smbc_setup_stat(context, st, path, size, mode);
- st->st_atime = a_time;
- st->st_ctime = c_time;
- st->st_mtime = m_time;
+ set_atimespec(st, access_time_ts);
+ set_ctimespec(st, change_time_ts);
+ set_mtimespec(st, write_time_ts);
st->st_dev = srv->dev;
return 0;
@@ -2134,9 +2150,9 @@ smbc_fstat_ctx(SMBCCTX *context,
SMBCFILE *file,
struct stat *st)
{
- time_t c_time;
- time_t a_time;
- time_t m_time;
+ struct timespec change_time_ts;
+ struct timespec access_time_ts;
+ struct timespec write_time_ts;
SMB_OFF_T size;
uint16 mode;
fstring server;
@@ -2183,7 +2199,7 @@ smbc_fstat_ctx(SMBCCTX *context,
}
/*d_printf(">>>fstat: resolving %s\n", path);*/
- if (!cli_resolve_path("", &file->srv->cli, path,
+ if (!cli_resolve_path("", file->srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -2192,22 +2208,33 @@ smbc_fstat_ctx(SMBCCTX *context,
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size,
- NULL, &a_time, &m_time, &c_time, &ino)) {
- if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size,
- &c_time, &a_time, &m_time)) {
+ NULL,
+ &access_time_ts,
+ &write_time_ts,
+ &change_time_ts,
+ &ino)) {
- errno = EINVAL;
- return -1;
- }
+ time_t change_time, access_time, write_time;
+
+ if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size,
+ &change_time, &access_time, &write_time)) {
+
+ errno = EINVAL;
+ return -1;
+ }
+
+ change_time_ts = convert_time_t_to_timespec(change_time);
+ access_time_ts = convert_time_t_to_timespec(access_time);
+ write_time_ts = convert_time_t_to_timespec(write_time);
}
st->st_ino = ino;
smbc_setup_stat(context, st, file->fname, size, mode);
- st->st_atime = a_time;
- st->st_ctime = c_time;
- st->st_mtime = m_time;
+ set_atimespec(st, access_time_ts);
+ set_ctimespec(st, change_time_ts);
+ set_mtimespec(st, write_time_ts);
st->st_dev = file->srv->dev;
return 0;
@@ -2256,7 +2283,7 @@ add_dirent(SMBCFILE *dir,
size = sizeof(struct smbc_dirent) + name_length + comment_len + 2;
- dirent = SMB_MALLOC(size);
+ dirent = (struct smbc_dirent *)SMB_MALLOC(size);
if (!dirent) {
@@ -2525,6 +2552,7 @@ static SMBCFILE *
smbc_opendir_ctx(SMBCCTX *context,
const char *fname)
{
+ int saved_errno;
fstring server, share, user, password, options;
pstring workgroup;
pstring path;
@@ -2532,6 +2560,7 @@ smbc_opendir_ctx(SMBCCTX *context,
char *p;
SMBCSRV *srv = NULL;
SMBCFILE *dir = NULL;
+ struct _smbc_callbacks *cb;
struct in_addr rem_ip;
if (!context || !context->internal ||
@@ -2684,7 +2713,7 @@ smbc_opendir_ctx(SMBCCTX *context,
/* Now, list the stuff ... */
- if (!cli_NetServerEnum(&srv->cli,
+ if (!cli_NetServerEnum(srv->cli,
workgroup,
SV_TYPE_DOMAIN_ENUM,
list_unique_wg_fn,
@@ -2780,7 +2809,7 @@ smbc_opendir_ctx(SMBCCTX *context,
dir->srv = srv;
/* Now, list the servers ... */
- if (!cli_NetServerEnum(&srv->cli, server,
+ if (!cli_NetServerEnum(srv->cli, server,
0x0000FFFE, list_fn,
(void *)dir)) {
@@ -2816,15 +2845,15 @@ smbc_opendir_ctx(SMBCCTX *context,
/* List the shares ... */
if (net_share_enum_rpc(
- &srv->cli,
+ srv->cli,
list_fn,
(void *) dir) < 0 &&
cli_RNetShareEnum(
- &srv->cli,
+ srv->cli,
list_fn,
(void *)dir) < 0) {
- errno = cli_errno(&srv->cli);
+ errno = cli_errno(srv->cli);
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
@@ -2874,7 +2903,7 @@ smbc_opendir_ctx(SMBCCTX *context,
p = path + strlen(path);
pstrcat(path, "\\*");
- if (!cli_resolve_path("", &srv->cli, path,
+ if (!cli_resolve_path("", srv->cli, path,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
@@ -2893,9 +2922,9 @@ smbc_opendir_ctx(SMBCCTX *context,
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
}
- errno = smbc_errno(context, targetcli);
+ saved_errno = smbc_errno(context, targetcli);
- if (errno == EINVAL) {
+ if (saved_errno == EINVAL) {
/*
* See if they asked to opendir something
* other than a directory. If so, the
@@ -2906,17 +2935,39 @@ smbc_opendir_ctx(SMBCCTX *context,
if (smbc_getatr(context, srv, path,
&mode, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
NULL) &&
! IS_DOS_DIR(mode)) {
/* It is. Correct the error value */
- errno = ENOTDIR;
+ saved_errno = ENOTDIR;
}
}
- return NULL;
+ /*
+ * If there was an error and the server is no
+ * good any more...
+ */
+ cb = &context->callbacks;
+ if (cli_is_error(targetcli) &&
+ cb->check_server_fn(context, srv)) {
+
+ /* ... then remove it. */
+ if (cb->remove_unused_server_fn(context,
+ srv)) {
+ /*
+ * We could not remove the server
+ * completely, remove it from the
+ * cache so we will not get it
+ * again. It will be removed when the
+ * last file/dir is closed.
+ */
+ cb->remove_cached_srv_fn(context, srv);
+ }
+ }
+ errno = saved_errno;
+ return NULL;
}
}
@@ -3223,7 +3274,7 @@ smbc_mkdir_ctx(SMBCCTX *context,
}
/*d_printf(">>>mkdir: resolving %s\n", path);*/
- if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath))
+ if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
return -1;
@@ -3320,7 +3371,7 @@ smbc_rmdir_ctx(SMBCCTX *context,
}
/*d_printf(">>>rmdir: resolving %s\n", path);*/
- if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath))
+ if (!cli_resolve_path( "", srv->cli, path, &targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
return -1;
@@ -3576,8 +3627,8 @@ smbc_chmod_ctx(SMBCCTX *context,
if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
- if (!cli_setatr(&srv->cli, path, mode, 0)) {
- errno = smbc_errno(context, &srv->cli);
+ if (!cli_setatr(srv->cli, path, mode, 0)) {
+ errno = smbc_errno(context, srv->cli);
return -1;
}
@@ -3596,8 +3647,8 @@ smbc_utimes_ctx(SMBCCTX *context,
fstring password;
fstring workgroup;
pstring path;
- time_t a_time;
- time_t m_time;
+ time_t access_time;
+ time_t write_time;
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -3615,10 +3666,10 @@ smbc_utimes_ctx(SMBCCTX *context,
}
if (tbuf == NULL) {
- a_time = m_time = time(NULL);
+ access_time = write_time = time(NULL);
} else {
- a_time = tbuf[0].tv_sec;
- m_time = tbuf[1].tv_sec;
+ access_time = tbuf[0].tv_sec;
+ write_time = tbuf[1].tv_sec;
}
if (DEBUGLVL(4))
@@ -3627,13 +3678,13 @@ smbc_utimes_ctx(SMBCCTX *context,
char atimebuf[32];
char mtimebuf[32];
- strncpy(atimebuf, ctime(&a_time), sizeof(atimebuf) - 1);
+ strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1);
atimebuf[sizeof(atimebuf) - 1] = '\0';
if ((p = strchr(atimebuf, '\n')) != NULL) {
*p = '\0';
}
- strncpy(mtimebuf, ctime(&m_time), sizeof(mtimebuf) - 1);
+ strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1);
mtimebuf[sizeof(mtimebuf) - 1] = '\0';
if ((p = strchr(mtimebuf, '\n')) != NULL) {
*p = '\0';
@@ -3664,7 +3715,8 @@ smbc_utimes_ctx(SMBCCTX *context,
return -1; /* errno set by smbc_server */
}
- if (!smbc_setatr(context, srv, path, 0, a_time, m_time, 0)) {
+ if (!smbc_setatr(context, srv, path,
+ 0, access_time, write_time, 0, 0)) {
return -1; /* errno set by smbc_setatr */
}
@@ -3693,8 +3745,8 @@ ace_compare(SEC_ACE *ace1,
if (ace1->flags != ace2->flags)
return ace1->flags - ace2->flags;
- if (ace1->info.mask != ace2->info.mask)
- return ace1->info.mask - ace2->info.mask;
+ if (ace1->access_mask != ace2->access_mask)
+ return ace1->access_mask - ace2->access_mask;
if (ace1->size != ace2->size)
return ace1->size - ace2->size;
@@ -3709,14 +3761,14 @@ sort_acl(SEC_ACL *the_acl)
uint32 i;
if (!the_acl) return;
- qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]),
+ qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]),
QSORT_CAST ace_compare);
for (i=1;i<the_acl->num_aces;) {
- if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) {
+ if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
int j;
for (j=i; j<the_acl->num_aces-1; j++) {
- the_acl->ace[j] = the_acl->ace[j+1];
+ the_acl->aces[j] = the_acl->aces[j+1];
}
the_acl->num_aces--;
} else {
@@ -3735,7 +3787,7 @@ convert_sid_to_string(struct cli_state *ipc_cli,
{
char **domains = NULL;
char **names = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
sid_to_string(str, sid);
@@ -3771,7 +3823,7 @@ convert_string_to_sid(struct cli_state *ipc_cli,
DOM_SID *sid,
const char *str)
{
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
DOM_SID *sids = NULL;
BOOL result = True;
struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
@@ -3921,7 +3973,7 @@ parse_ace(struct cli_state *ipc_cli,
}
done:
- mask.mask = amask;
+ mask = amask;
init_sec_ace(ace, &sid, atype, mask, aflags);
return True;
}
@@ -3943,7 +3995,7 @@ add_ace(SEC_ACL **the_acl,
if ((aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces)) == NULL) {
return False;
}
- memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE));
+ memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
newacl = make_sec_acl(ctx, (*the_acl)->revision,
1+(*the_acl)->num_aces, aces);
@@ -3965,7 +4017,7 @@ sec_desc_parse(TALLOC_CTX *ctx,
fstring tok;
SEC_DESC *ret = NULL;
size_t sd_size;
- DOM_SID *grp_sid=NULL;
+ DOM_SID *group_sid=NULL;
DOM_SID *owner_sid=NULL;
SEC_ACL *dacl=NULL;
int revision=1;
@@ -4010,15 +4062,15 @@ sec_desc_parse(TALLOC_CTX *ctx,
}
if (StrnCaseCmp(tok,"GROUP:", 6) == 0) {
- if (grp_sid) {
+ if (group_sid) {
DEBUG(5, ("GROUP specified more than once!\n"));
goto done;
}
- grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
- if (!grp_sid ||
+ group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
+ if (!group_sid ||
!convert_string_to_sid(ipc_cli, pol,
numeric,
- grp_sid, tok+6)) {
+ group_sid, tok+6)) {
DEBUG(5, ("Failed to parse group sid\n"));
goto done;
}
@@ -4026,15 +4078,15 @@ sec_desc_parse(TALLOC_CTX *ctx,
}
if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) {
- if (grp_sid) {
+ if (group_sid) {
DEBUG(5, ("GROUP specified more than once!\n"));
goto done;
}
- grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
- if (!grp_sid ||
+ group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
+ if (!group_sid ||
!convert_string_to_sid(ipc_cli, pol,
False,
- grp_sid, tok+6)) {
+ group_sid, tok+6)) {
DEBUG(5, ("Failed to parse group sid\n"));
goto done;
}
@@ -4072,10 +4124,10 @@ sec_desc_parse(TALLOC_CTX *ctx,
}
ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE,
- owner_sid, grp_sid, NULL, dacl, &sd_size);
+ owner_sid, group_sid, NULL, dacl, &sd_size);
done:
- SAFE_FREE(grp_sid);
+ SAFE_FREE(group_sid);
SAFE_FREE(owner_sid);
return ret;
@@ -4089,7 +4141,10 @@ dos_attr_query(SMBCCTX *context,
const char *filename,
SMBCSRV *srv)
{
- time_t m_time = 0, a_time = 0, c_time = 0;
+ struct timespec create_time_ts;
+ struct timespec write_time_ts;
+ struct timespec access_time_ts;
+ struct timespec change_time_ts;
SMB_OFF_T size = 0;
uint16 mode = 0;
SMB_INO_T inode = 0;
@@ -4104,9 +4159,13 @@ dos_attr_query(SMBCCTX *context,
/* Obtain the DOS attributes */
if (!smbc_getatr(context, srv, CONST_DISCARD(char *, filename),
&mode, &size,
- &c_time, &a_time, &m_time, &inode)) {
+ &create_time_ts,
+ &access_time_ts,
+ &write_time_ts,
+ &change_time_ts,
+ &inode)) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
return NULL;
@@ -4114,9 +4173,10 @@ dos_attr_query(SMBCCTX *context,
ret->mode = mode;
ret->size = size;
- ret->a_time = a_time;
- ret->c_time = c_time;
- ret->m_time = m_time;
+ ret->create_time = convert_timespec_to_time_t(create_time_ts);
+ ret->access_time = convert_timespec_to_time_t(access_time_ts);
+ ret->write_time = convert_timespec_to_time_t(write_time_ts);
+ ret->change_time = convert_timespec_to_time_t(change_time_ts);
ret->inode = inode;
return ret;
@@ -4130,8 +4190,40 @@ dos_attr_parse(SMBCCTX *context,
SMBCSRV *srv,
char *str)
{
- const char *p = str;
+ int n;
+ const char *p = str;
fstring tok;
+ struct {
+ const char * create_time_attr;
+ const char * access_time_attr;
+ const char * write_time_attr;
+ const char * change_time_attr;
+ } attr_strings;
+
+ /* Determine whether to use old-style or new-style attribute names */
+ if (context->internal->_full_time_names) {
+ /* new-style names */
+ attr_strings.create_time_attr = "CREATE_TIME";
+ attr_strings.access_time_attr = "ACCESS_TIME";
+ attr_strings.write_time_attr = "WRITE_TIME";
+ attr_strings.change_time_attr = "CHANGE_TIME";
+ } else {
+ /* old-style names */
+ attr_strings.create_time_attr = NULL;
+ attr_strings.access_time_attr = "A_TIME";
+ attr_strings.write_time_attr = "M_TIME";
+ attr_strings.change_time_attr = "C_TIME";
+ }
+
+ /* if this is to set the entire ACL... */
+ if (*str == '*') {
+ /* ... then increment past the first colon if there is one */
+ if ((p = strchr(str, ':')) != NULL) {
+ ++p;
+ } else {
+ p = str;
+ }
+ }
while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) {
@@ -4145,21 +4237,34 @@ dos_attr_parse(SMBCCTX *context,
continue;
}
- if (StrnCaseCmp(tok, "A_TIME:", 7) == 0) {
- dad->a_time = (time_t)strtol(tok+7, NULL, 10);
+ n = strlen(attr_strings.access_time_attr);
+ if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) {
+ dad->access_time = (time_t)strtol(tok+n+1, NULL, 10);
continue;
}
- if (StrnCaseCmp(tok, "C_TIME:", 7) == 0) {
- dad->c_time = (time_t)strtol(tok+7, NULL, 10);
+ n = strlen(attr_strings.change_time_attr);
+ if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) {
+ dad->change_time = (time_t)strtol(tok+n+1, NULL, 10);
continue;
}
- if (StrnCaseCmp(tok, "M_TIME:", 7) == 0) {
- dad->m_time = (time_t)strtol(tok+7, NULL, 10);
+ n = strlen(attr_strings.write_time_attr);
+ if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) {
+ dad->write_time = (time_t)strtol(tok+n+1, NULL, 10);
continue;
}
+ if (attr_strings.create_time_attr != NULL) {
+ n = strlen(attr_strings.create_time_attr);
+ if (StrnCaseCmp(tok, attr_strings.create_time_attr,
+ n) == 0) {
+ dad->create_time = (time_t)strtol(tok+n+1,
+ NULL, 10);
+ continue;
+ }
+ }
+
if (StrnCaseCmp(tok, "INODE:", 6) == 0) {
dad->inode = (SMB_INO_T)atof(tok+6);
continue;
@@ -4197,9 +4302,10 @@ cacl_get(SMBCCTX *context,
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_create_time = False;
+ BOOL exclude_dos_access_time = False;
+ BOOL exclude_dos_write_time = False;
+ BOOL exclude_dos_change_time = False;
BOOL exclude_dos_inode = False;
BOOL numeric = True;
BOOL determine_size = (bufsize == 0);
@@ -4210,11 +4316,55 @@ cacl_get(SMBCCTX *context,
char *name;
char *pExclude;
char *p;
- time_t m_time = 0, a_time = 0, c_time = 0;
+ struct timespec create_time_ts;
+ struct timespec write_time_ts;
+ struct timespec access_time_ts;
+ struct timespec change_time_ts;
+ time_t create_time = (time_t)0;
+ time_t write_time = (time_t)0;
+ time_t access_time = (time_t)0;
+ time_t change_time = (time_t)0;
SMB_OFF_T size = 0;
uint16 mode = 0;
SMB_INO_T ino = 0;
- struct cli_state *cli = &srv->cli;
+ struct cli_state *cli = srv->cli;
+ struct {
+ const char * create_time_attr;
+ const char * access_time_attr;
+ const char * write_time_attr;
+ const char * change_time_attr;
+ } attr_strings;
+ struct {
+ const char * create_time_attr;
+ const char * access_time_attr;
+ const char * write_time_attr;
+ const char * change_time_attr;
+ } excl_attr_strings;
+
+ /* Determine whether to use old-style or new-style attribute names */
+ if (context->internal->_full_time_names) {
+ /* new-style names */
+ attr_strings.create_time_attr = "CREATE_TIME";
+ attr_strings.access_time_attr = "ACCESS_TIME";
+ attr_strings.write_time_attr = "WRITE_TIME";
+ attr_strings.change_time_attr = "CHANGE_TIME";
+
+ excl_attr_strings.create_time_attr = "CREATE_TIME";
+ excl_attr_strings.access_time_attr = "ACCESS_TIME";
+ excl_attr_strings.write_time_attr = "WRITE_TIME";
+ excl_attr_strings.change_time_attr = "CHANGE_TIME";
+ } else {
+ /* old-style names */
+ attr_strings.create_time_attr = NULL;
+ attr_strings.access_time_attr = "A_TIME";
+ attr_strings.write_time_attr = "M_TIME";
+ attr_strings.change_time_attr = "C_TIME";
+
+ excl_attr_strings.create_time_attr = NULL;
+ excl_attr_strings.access_time_attr = "dos_attr.A_TIME";
+ excl_attr_strings.write_time_attr = "dos_attr.M_TIME";
+ excl_attr_strings.change_time_attr = "dos_attr.C_TIME";
+ }
/* Copy name so we can strip off exclusions (if any are specified) */
strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1);
@@ -4272,14 +4422,22 @@ cacl_get(SMBCCTX *context,
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 (excl_attr_strings.create_time_attr != NULL &&
+ StrCaseCmp(pExclude,
+ excl_attr_strings.change_time_attr) == 0) {
+ exclude_dos_create_time = True;
}
- else if (StrCaseCmp(pExclude, "dos_attr.a_time") == 0) {
- exclude_dos_atime = True;
+ else if (StrCaseCmp(pExclude,
+ excl_attr_strings.access_time_attr) == 0) {
+ exclude_dos_access_time = True;
}
- else if (StrCaseCmp(pExclude, "dos_attr.m_time") == 0) {
- exclude_dos_mtime = True;
+ else if (StrCaseCmp(pExclude,
+ excl_attr_strings.write_time_attr) == 0) {
+ exclude_dos_write_time = True;
+ }
+ else if (StrCaseCmp(pExclude,
+ excl_attr_strings.change_time_attr) == 0) {
+ exclude_dos_change_time = True;
}
else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) {
exclude_dos_inode = True;
@@ -4412,10 +4570,10 @@ cacl_get(SMBCCTX *context,
}
if (! exclude_nt_group) {
- if (sd->grp_sid) {
+ if (sd->group_sid) {
convert_sid_to_string(ipc_cli, pol,
sidstr, numeric,
- sd->grp_sid);
+ sd->group_sid);
} else {
fstrcpy(sidstr, "");
}
@@ -4460,7 +4618,7 @@ cacl_get(SMBCCTX *context,
/* Add aces to value buffer */
for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
- SEC_ACE *ace = &sd->dacl->ace[i];
+ SEC_ACE *ace = &sd->dacl->aces[i];
convert_sid_to_string(ipc_cli, pol,
sidstr, numeric,
&ace->trustee);
@@ -4474,7 +4632,7 @@ cacl_get(SMBCCTX *context,
sidstr,
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4487,7 +4645,7 @@ cacl_get(SMBCCTX *context,
sidstr,
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
}
} else if ((StrnCaseCmp(name, "acl", 3) == 0 &&
StrCaseCmp(name+3, sidstr) == 0) ||
@@ -4499,7 +4657,7 @@ cacl_get(SMBCCTX *context,
"%d/%d/0x%08x",
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4510,7 +4668,7 @@ cacl_get(SMBCCTX *context,
"%d/%d/0x%08x",
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
}
} else if (all_nt_acls) {
if (determine_size) {
@@ -4521,7 +4679,7 @@ cacl_get(SMBCCTX *context,
sidstr,
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4534,7 +4692,7 @@ cacl_get(SMBCCTX *context,
sidstr,
ace->type,
ace->flags,
- ace->info.mask);
+ ace->access_mask);
}
}
if (n > bufsize) {
@@ -4557,13 +4715,22 @@ cacl_get(SMBCCTX *context,
/* Obtain the DOS attributes */
if (!smbc_getatr(context, srv, filename, &mode, &size,
- &c_time, &a_time, &m_time, &ino)) {
+ &create_time_ts,
+ &access_time_ts,
+ &write_time_ts,
+ &change_time_ts,
+ &ino)) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
return -1;
}
-
+
+ create_time = convert_timespec_to_time_t(create_time_ts);
+ access_time = convert_timespec_to_time_t(access_time_ts);
+ write_time = convert_timespec_to_time_t(write_time_ts);
+ change_time = convert_timespec_to_time_t(change_time_ts);
+
if (! exclude_dos_mode) {
if (all || all_dos) {
if (determine_size) {
@@ -4655,12 +4822,14 @@ cacl_get(SMBCCTX *context,
bufsize -= n;
}
- if (! exclude_dos_ctime) {
+ if (! exclude_dos_create_time &&
+ attr_strings.create_time_attr != NULL) {
if (all || all_dos) {
if (determine_size) {
p = talloc_asprintf(ctx,
- ",C_TIME:%lu",
- c_time);
+ ",%s:%lu",
+ attr_strings.create_time_attr,
+ create_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4668,11 +4837,13 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- ",C_TIME:%lu", c_time);
+ ",%s:%lu",
+ attr_strings.create_time_attr,
+ create_time);
}
- } else if (StrCaseCmp(name, "c_time") == 0) {
+ } else if (StrCaseCmp(name, attr_strings.create_time_attr) == 0) {
if (determine_size) {
- p = talloc_asprintf(ctx, "%lu", c_time);
+ p = talloc_asprintf(ctx, "%lu", create_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4680,7 +4851,7 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- "%lu", c_time);
+ "%lu", create_time);
}
}
@@ -4693,12 +4864,13 @@ cacl_get(SMBCCTX *context,
bufsize -= n;
}
- if (! exclude_dos_atime) {
+ if (! exclude_dos_access_time) {
if (all || all_dos) {
if (determine_size) {
p = talloc_asprintf(ctx,
- ",A_TIME:%lu",
- a_time);
+ ",%s:%lu",
+ attr_strings.access_time_attr,
+ access_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4706,11 +4878,13 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- ",A_TIME:%lu", a_time);
+ ",%s:%lu",
+ attr_strings.access_time_attr,
+ access_time);
}
- } else if (StrCaseCmp(name, "a_time") == 0) {
+ } else if (StrCaseCmp(name, attr_strings.access_time_attr) == 0) {
if (determine_size) {
- p = talloc_asprintf(ctx, "%lu", a_time);
+ p = talloc_asprintf(ctx, "%lu", access_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4718,7 +4892,7 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- "%lu", a_time);
+ "%lu", access_time);
}
}
@@ -4731,12 +4905,13 @@ cacl_get(SMBCCTX *context,
bufsize -= n;
}
- if (! exclude_dos_mtime) {
+ if (! exclude_dos_write_time) {
if (all || all_dos) {
if (determine_size) {
p = talloc_asprintf(ctx,
- ",M_TIME:%lu",
- m_time);
+ ",%s:%lu",
+ attr_strings.write_time_attr,
+ write_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4744,11 +4919,13 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- ",M_TIME:%lu", m_time);
+ ",%s:%lu",
+ attr_strings.write_time_attr,
+ write_time);
}
- } else if (StrCaseCmp(name, "m_time") == 0) {
+ } else if (StrCaseCmp(name, attr_strings.write_time_attr) == 0) {
if (determine_size) {
- p = talloc_asprintf(ctx, "%lu", m_time);
+ p = talloc_asprintf(ctx, "%lu", write_time);
if (!p) {
errno = ENOMEM;
return -1;
@@ -4756,7 +4933,48 @@ cacl_get(SMBCCTX *context,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- "%lu", m_time);
+ "%lu", write_time);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
+ }
+
+ if (! exclude_dos_change_time) {
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",%s:%lu",
+ attr_strings.change_time_attr,
+ change_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",%s:%lu",
+ attr_strings.change_time_attr,
+ change_time);
+ }
+ } else if (StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%lu", change_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ "%lu", change_time);
}
}
@@ -4844,7 +5062,7 @@ cacl_set(TALLOC_CTX *ctx,
SEC_DESC *sd = NULL, *old;
SEC_ACL *dacl = NULL;
DOM_SID *owner_sid = NULL;
- DOM_SID *grp_sid = NULL;
+ DOM_SID *group_sid = NULL;
uint32 i, j;
size_t sd_size;
int ret = 0;
@@ -4905,9 +5123,9 @@ cacl_set(TALLOC_CTX *ctx,
switch (mode) {
case SMBC_XATTR_MODE_REMOVE_ALL:
old->dacl->num_aces = 0;
- SAFE_FREE(old->dacl->ace);
+ SAFE_FREE(old->dacl->aces);
SAFE_FREE(old->dacl);
- old->off_dacl = 0;
+ old->dacl = NULL;
dacl = old->dacl;
break;
@@ -4916,18 +5134,18 @@ cacl_set(TALLOC_CTX *ctx,
BOOL found = False;
for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
- if (sec_ace_equal(&sd->dacl->ace[i],
- &old->dacl->ace[j])) {
+ if (sec_ace_equal(&sd->dacl->aces[i],
+ &old->dacl->aces[j])) {
uint32 k;
for (k=j; k<old->dacl->num_aces-1;k++) {
- old->dacl->ace[k] =
- old->dacl->ace[k+1];
+ old->dacl->aces[k] =
+ old->dacl->aces[k+1];
}
old->dacl->num_aces--;
if (old->dacl->num_aces == 0) {
- SAFE_FREE(old->dacl->ace);
+ SAFE_FREE(old->dacl->aces);
SAFE_FREE(old->dacl);
- old->off_dacl = 0;
+ old->dacl = NULL;
}
found = True;
dacl = old->dacl;
@@ -4948,14 +5166,14 @@ cacl_set(TALLOC_CTX *ctx,
BOOL found = False;
for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
- if (sid_equal(&sd->dacl->ace[i].trustee,
- &old->dacl->ace[j].trustee)) {
+ if (sid_equal(&sd->dacl->aces[i].trustee,
+ &old->dacl->aces[j].trustee)) {
if (!(flags & SMBC_XATTR_FLAG_CREATE)) {
err = EEXIST;
ret = -1;
goto failed;
}
- old->dacl->ace[j] = sd->dacl->ace[i];
+ old->dacl->aces[j] = sd->dacl->aces[i];
ret = -1;
found = True;
}
@@ -4968,7 +5186,7 @@ cacl_set(TALLOC_CTX *ctx,
}
for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
- add_ace(&old->dacl, &sd->dacl->ace[i], ctx);
+ add_ace(&old->dacl, &sd->dacl->aces[i], ctx);
}
}
dacl = old->dacl;
@@ -4977,7 +5195,7 @@ cacl_set(TALLOC_CTX *ctx,
case SMBC_XATTR_MODE_SET:
old = sd;
owner_sid = old->owner_sid;
- grp_sid = old->grp_sid;
+ group_sid = old->group_sid;
dacl = old->dacl;
break;
@@ -4986,7 +5204,7 @@ cacl_set(TALLOC_CTX *ctx,
break;
case SMBC_XATTR_MODE_CHGRP:
- grp_sid = sd->grp_sid;
+ group_sid = sd->group_sid;
break;
}
@@ -4995,7 +5213,7 @@ cacl_set(TALLOC_CTX *ctx,
/* Create new security descriptor and set it */
sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE,
- owner_sid, grp_sid, NULL, dacl, &sd_size);
+ owner_sid, group_sid, NULL, dacl, &sd_size);
fnum = cli_nt_create(cli, filename,
WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
@@ -5046,6 +5264,12 @@ smbc_setxattr_ctx(SMBCCTX *context,
TALLOC_CTX *ctx;
POLICY_HND pol;
DOS_ATTR_DESC *dad;
+ struct {
+ const char * create_time_attr;
+ const char * access_time_attr;
+ const char * write_time_attr;
+ const char * change_time_attr;
+ } attr_strings;
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -5116,8 +5340,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
}
if (ipc_srv) {
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
namevalue,
(*namevalue == '*'
? SMBC_XATTR_MODE_SET
@@ -5135,9 +5359,10 @@ smbc_setxattr_ctx(SMBCCTX *context,
/* Set the new DOS attributes */
if (! smbc_setatr(context, srv, path,
- dad->c_time,
- dad->a_time,
- dad->m_time,
+ dad->create_time,
+ dad->access_time,
+ dad->write_time,
+ dad->change_time,
dad->mode)) {
/* cause failure if NT failed too */
@@ -5179,8 +5404,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
errno = ENOMEM;
ret = -1;
} else {
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
namevalue,
(*namevalue == '*'
? SMBC_XATTR_MODE_SET
@@ -5210,8 +5435,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
errno = ENOMEM;
ret = -1;
} else {
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
namevalue, SMBC_XATTR_MODE_CHOWN, 0);
}
talloc_destroy(ctx);
@@ -5237,22 +5462,39 @@ smbc_setxattr_ctx(SMBCCTX *context,
errno = ENOMEM;
ret = -1;
} else {
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
namevalue, SMBC_XATTR_MODE_CHOWN, 0);
}
talloc_destroy(ctx);
return ret;
}
+ /* Determine whether to use old-style or new-style attribute names */
+ if (context->internal->_full_time_names) {
+ /* new-style names */
+ attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
+ attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
+ attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
+ attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
+ } else {
+ /* old-style names */
+ attr_strings.create_time_attr = NULL;
+ attr_strings.access_time_attr = "system.dos_attr.A_TIME";
+ attr_strings.write_time_attr = "system.dos_attr.M_TIME";
+ attr_strings.change_time_attr = "system.dos_attr.C_TIME";
+ }
+
/*
* Are they asking to set a DOS attribute?
*/
if (StrCaseCmp(name, "system.dos_attr.*") == 0 ||
StrCaseCmp(name, "system.dos_attr.mode") == 0 ||
- StrCaseCmp(name, "system.dos_attr.c_time") == 0 ||
- StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
- StrCaseCmp(name, "system.dos_attr.m_time") == 0) {
+ (attr_strings.create_time_attr != NULL &&
+ StrCaseCmp(name, attr_strings.create_time_attr) == 0) ||
+ StrCaseCmp(name, attr_strings.access_time_attr) == 0 ||
+ StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
+ StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
/* get a DOS Attribute Descriptor with current attributes */
dad = dos_attr_query(context, ctx, path, srv);
@@ -5269,9 +5511,10 @@ smbc_setxattr_ctx(SMBCCTX *context,
/* Set the new DOS attributes */
ret2 = smbc_setatr(context, srv, path,
- dad->c_time,
- dad->a_time,
- dad->m_time,
+ dad->create_time,
+ dad->access_time,
+ dad->write_time,
+ dad->change_time,
dad->mode);
/* ret2 has True (success) / False (failure) */
@@ -5313,6 +5556,12 @@ smbc_getxattr_ctx(SMBCCTX *context,
pstring path;
TALLOC_CTX *ctx;
POLICY_HND pol;
+ struct {
+ const char * create_time_attr;
+ const char * access_time_attr;
+ const char * write_time_attr;
+ const char * change_time_attr;
+ } attr_strings;
if (!context || !context->internal ||
@@ -5369,6 +5618,21 @@ smbc_getxattr_ctx(SMBCCTX *context,
return -1;
}
+ /* Determine whether to use old-style or new-style attribute names */
+ if (context->internal->_full_time_names) {
+ /* new-style names */
+ attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
+ attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
+ attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
+ attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
+ } else {
+ /* old-style names */
+ attr_strings.create_time_attr = NULL;
+ attr_strings.access_time_attr = "system.dos_attr.A_TIME";
+ attr_strings.write_time_attr = "system.dos_attr.M_TIME";
+ attr_strings.change_time_attr = "system.dos_attr.C_TIME";
+ }
+
/* Are they requesting a supported attribute? */
if (StrCaseCmp(name, "system.*") == 0 ||
StrnCaseCmp(name, "system.*!", 9) == 0 ||
@@ -5389,19 +5653,21 @@ smbc_getxattr_ctx(SMBCCTX *context,
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 ||
- StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
- StrCaseCmp(name, "system.dos_attr.m_time") == 0 ||
+ (attr_strings.create_time_attr != NULL &&
+ StrCaseCmp(name, attr_strings.create_time_attr) == 0) ||
+ StrCaseCmp(name, attr_strings.access_time_attr) == 0 ||
+ StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
+ StrCaseCmp(name, attr_strings.change_time_attr) == 0 ||
StrCaseCmp(name, "system.dos_attr.inode") == 0) {
/* Yup. */
ret = cacl_get(context, ctx, srv,
- ipc_srv == NULL ? NULL : &ipc_srv->cli,
+ ipc_srv == NULL ? NULL : ipc_srv->cli,
&pol, path,
CONST_DISCARD(char *, name),
CONST_DISCARD(char *, value), size);
if (ret < 0 && errno == 0) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
}
talloc_destroy(ctx);
return ret;
@@ -5492,8 +5758,8 @@ smbc_removexattr_ctx(SMBCCTX *context,
StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) {
/* Yup. */
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0);
talloc_destroy(ctx);
return ret;
@@ -5512,8 +5778,8 @@ smbc_removexattr_ctx(SMBCCTX *context,
StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
/* Yup. */
- ret = cacl_set(ctx, &srv->cli,
- &ipc_srv->cli, &pol, path,
+ ret = cacl_set(ctx, srv->cli,
+ ipc_srv->cli, &pol, path,
name + 19, SMBC_XATTR_MODE_REMOVE, 0);
talloc_destroy(ctx);
return ret;
@@ -5536,7 +5802,7 @@ smbc_listxattr_ctx(SMBCCTX *context,
* the complete set of attribute names, always, rather than only those
* attribute names which actually exist for a file. Hmmm...
*/
- const char supported[] =
+ const char supported_old[] =
"system.*\0"
"system.*+\0"
"system.nt_sec_desc.revision\0"
@@ -5555,6 +5821,33 @@ smbc_listxattr_ctx(SMBCCTX *context,
"system.dos_attr.a_time\0"
"system.dos_attr.m_time\0"
;
+ const char supported_new[] =
+ "system.*\0"
+ "system.*+\0"
+ "system.nt_sec_desc.revision\0"
+ "system.nt_sec_desc.owner\0"
+ "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"
+ "system.nt_sec_desc.*+\0"
+ "system.dos_attr.*\0"
+ "system.dos_attr.mode\0"
+ "system.dos_attr.create_time\0"
+ "system.dos_attr.access_time\0"
+ "system.dos_attr.write_time\0"
+ "system.dos_attr.change_time\0"
+ ;
+ const char * supported;
+
+ if (context->internal->_full_time_names) {
+ supported = supported_new;
+ } else {
+ supported = supported_old;
+ }
if (size == 0) {
return sizeof(supported);
@@ -5763,10 +6056,10 @@ smbc_list_print_jobs_ctx(SMBCCTX *context,
}
- if (cli_print_queue(&srv->cli,
+ if (cli_print_queue(srv->cli,
(void (*)(struct print_job_info *))fn) < 0) {
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
return -1;
}
@@ -5833,10 +6126,10 @@ smbc_unlink_print_job_ctx(SMBCCTX *context,
}
- if ((err = cli_printjob_del(&srv->cli, id)) != 0) {
+ if ((err = cli_printjob_del(srv->cli, id)) != 0) {
if (err < 0)
- errno = smbc_errno(context, &srv->cli);
+ errno = smbc_errno(context, srv->cli);
else if (err == ERRnosuchprintjob)
errno = EINVAL;
return -1;
@@ -5880,6 +6173,8 @@ smbc_new_context(void)
context->options.browse_max_lmb_count = 3; /* # LMBs to query */
context->options.urlencode_readdir_entries = False;/* backward compat */
context->options.one_share_per_server = False;/* backward compat */
+ context->internal->_share_mode = SMBC_SHAREMODE_DENY_NONE;
+ /* backward compat */
context->open = smbc_open_ctx;
context->creat = smbc_creat_ctx;
@@ -5955,8 +6250,8 @@ smbc_free_context(SMBCCTX *context,
s = context->internal->_servers;
while (s) {
DEBUG(1, ("Forced shutdown: %p (fd=%d)\n",
- s, s->cli.fd));
- cli_shutdown(&s->cli);
+ s, s->cli->fd));
+ cli_shutdown(s->cli);
context->callbacks.remove_cached_srv_fn(context,
s);
next = s->next;
@@ -6011,27 +6306,65 @@ smbc_free_context(SMBCCTX *context,
void
smbc_option_set(SMBCCTX *context,
char *option_name,
- void *option_value)
+ ... /* option_value */)
{
- if (strcmp(option_name, "debug_stderr") == 0) {
+ va_list ap;
+ union {
+ int i;
+ BOOL b;
+ smbc_get_auth_data_with_context_fn auth_fn;
+ void *v;
+ } option_value;
+
+ va_start(ap, option_name);
+
+ if (strcmp(option_name, "debug_to_stderr") == 0) {
/*
* Log to standard error instead of standard output.
*/
- context->internal->_debug_stderr =
- (option_value == NULL ? False : True);
+ option_value.b = (BOOL) va_arg(ap, int);
+ context->internal->_debug_stderr = option_value.b;
+
+ } else if (strcmp(option_name, "full_time_names") == 0) {
+ /*
+ * Use new-style time attribute names, e.g. WRITE_TIME rather
+ * than the old-style names such as M_TIME. This allows also
+ * setting/getting CREATE_TIME which was previously
+ * unimplemented. (Note that the old C_TIME was supposed to
+ * be CHANGE_TIME but was confused and sometimes referred to
+ * CREATE_TIME.)
+ */
+ option_value.b = (BOOL) va_arg(ap, int);
+ context->internal->_full_time_names = option_value.b;
+
+ } else if (strcmp(option_name, "open_share_mode") == 0) {
+ /*
+ * The share mode to use for files opened with
+ * smbc_open_ctx(). The default is SMBC_SHAREMODE_DENY_NONE.
+ */
+ option_value.i = va_arg(ap, int);
+ context->internal->_share_mode =
+ (smbc_share_mode) option_value.i;
+
} else if (strcmp(option_name, "auth_function") == 0) {
/*
* Use the new-style authentication function which includes
* the context.
*/
- context->internal->_auth_fn_with_context = option_value;
+ option_value.auth_fn =
+ va_arg(ap, smbc_get_auth_data_with_context_fn);
+ context->internal->_auth_fn_with_context =
+ option_value.auth_fn;
} else if (strcmp(option_name, "user_data") == 0) {
/*
* Save a user data handle which may be retrieved by the user
* with smbc_option_get()
*/
- context->internal->_user_data = option_value;
+ option_value.v = va_arg(ap, void *);
+ context->internal->_user_data = option_value.v;
}
+
+ va_end(ap);
}
@@ -6047,10 +6380,25 @@ smbc_option_get(SMBCCTX *context,
* Log to standard error instead of standard output.
*/
#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
- return (void *) (intptr_t) context->internal->_debug_stderr;
+ return (void *) (intptr_t) context->internal->_debug_stderr;
+#else
+ return (void *) context->internal->_debug_stderr;
+#endif
+ } else if (strcmp(option_name, "full_time_names") == 0) {
+ /*
+ * Use new-style time attribute names, e.g. WRITE_TIME rather
+ * than the old-style names such as M_TIME. This allows also
+ * setting/getting CREATE_TIME which was previously
+ * unimplemented. (Note that the old C_TIME was supposed to
+ * be CHANGE_TIME but was confused and sometimes referred to
+ * CREATE_TIME.)
+ */
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+ return (void *) (intptr_t) context->internal->_full_time_names;
#else
- return (void *) context->internal->_debug_stderr;
+ return (void *) context->internal->_full_time_names;
#endif
+
} else if (strcmp(option_name, "auth_function") == 0) {
/*
* Use the new-style authentication function which includes
@@ -6205,7 +6553,7 @@ smbc_init_context(SMBCCTX *context)
* lazy for the moment
*/
pid = sys_getpid();
- context->netbios_name = SMB_MALLOC(17);
+ context->netbios_name = (char *)SMB_MALLOC(17);
if (!context->netbios_name) {
errno = ENOMEM;
return NULL;
diff --git a/source/libsmb/namecache.c b/source/libsmb/namecache.c
index ec8a1900d87..02956fa1371 100644
--- a/source/libsmb/namecache.c
+++ b/source/libsmb/namecache.c
@@ -126,6 +126,10 @@ BOOL namecache_store(const char *name, int name_type,
*/
if (!gencache_init()) return False;
+ if (name_type > 255) {
+ return False; /* Don't store non-real name types. */
+ }
+
if ( DEBUGLEVEL >= 5 ) {
DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
num_names, num_names == 1 ? "": "es", name, name_type));
@@ -138,6 +142,10 @@ BOOL namecache_store(const char *name, int name_type,
}
key = namecache_key(name, name_type);
+ if (!key) {
+ return False;
+ }
+
expiry = time(NULL) + lp_name_cache_timeout();
/*
@@ -184,18 +192,23 @@ BOOL namecache_fetch(const char *name, int name_type, struct ip_service **ip_lis
if (!gencache_init())
return False;
+ if (name_type > 255) {
+ return False; /* Don't fetch non-real name types. */
+ }
+
*num_names = 0;
/*
* Use gencache interface - lookup the key
*/
key = namecache_key(name, name_type);
+ if (!key) {
+ return False;
+ }
if (!gencache_get(key, &value, &timeout)) {
DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type));
- gencache_del(key);
SAFE_FREE(key);
- SAFE_FREE(value);
return False;
} else {
DEBUG(5, ("name %s#%02X found.\n", name, name_type));
@@ -212,6 +225,31 @@ BOOL namecache_fetch(const char *name, int name_type, struct ip_service **ip_lis
return *num_names > 0; /* true only if some ip has been fetched */
}
+/**
+ * Remove a namecache entry. Needed for site support.
+ *
+ **/
+
+BOOL namecache_delete(const char *name, int name_type)
+{
+ BOOL ret;
+ char *key;
+
+ if (!gencache_init())
+ return False;
+
+ if (name_type > 255) {
+ return False; /* Don't fetch non-real name types. */
+ }
+
+ key = namecache_key(name, name_type);
+ if (!key) {
+ return False;
+ }
+ ret = gencache_del(key);
+ SAFE_FREE(key);
+ return ret;
+}
/**
* Delete single namecache entry. Look at the
@@ -306,9 +344,7 @@ BOOL namecache_status_fetch(const char *keyname, int keyname_type,
if (!gencache_get(key, &value, &timeout)) {
DEBUG(5, ("namecache_status_fetch: no entry for %s found.\n", key));
- gencache_del(key);
SAFE_FREE(key);
- SAFE_FREE(value);
return False;
} else {
DEBUG(5, ("namecache_status_fetch: key %s -> %s\n", key, value ));
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 718cf28d22e..cbd94ff5672 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -15,8 +15,7 @@
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.
-
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
@@ -24,7 +23,6 @@
/* nmbd.c sets this to True. */
BOOL global_in_nmbd = False;
-
/****************************
* SERVER AFFINITY ROUTINES *
****************************/
@@ -59,6 +57,11 @@ BOOL saf_store( const char *domain, const char *servername )
DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
return False;
}
+
+ if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
+ DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
+ return False;
+ }
if ( !gencache_init() )
return False;
@@ -77,6 +80,31 @@ BOOL saf_store( const char *domain, const char *servername )
return ret;
}
+BOOL saf_delete( const char *domain )
+{
+ char *key;
+ BOOL ret = False;
+
+ if ( !domain ) {
+ DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
+ return False;
+ }
+
+ if ( !gencache_init() )
+ return False;
+
+ key = saf_key(domain);
+ ret = gencache_del(key);
+
+ if (ret) {
+ DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
+ }
+
+ SAFE_FREE( key );
+
+ return ret;
+}
+
/****************************************************************************
****************************************************************************/
@@ -87,7 +115,7 @@ char *saf_fetch( const char *domain )
BOOL ret = False;
char *key = NULL;
- if ( !domain ) {
+ if ( !domain || strlen(domain) == 0) {
DEBUG(2,("saf_fetch: Empty domain name!\n"));
return NULL;
}
@@ -111,7 +139,6 @@ char *saf_fetch( const char *domain )
return server;
}
-
/****************************************************************************
Generate a random trn_id.
****************************************************************************/
@@ -357,7 +384,7 @@ static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
compare 2 ldap IPs by nearness to our interfaces - used in qsort
*******************************************************************/
-static int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
+int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
{
int result;
@@ -1022,6 +1049,7 @@ static BOOL resolve_hosts(const char *name, int name_type,
*********************************************************/
static BOOL resolve_ads(const char *name, int name_type,
+ const char *sitename,
struct ip_service **return_iplist, int *return_count)
{
int i, j;
@@ -1031,7 +1059,7 @@ static BOOL resolve_ads(const char *name, int name_type,
int numdcs = 0;
int numaddrs = 0;
- if ( name_type != 0x1c )
+ if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
return False;
DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
@@ -1041,8 +1069,12 @@ static BOOL resolve_ads(const char *name, int name_type,
DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
return False;
}
-
- status = ads_dns_query_dcs( ctx, name, &dcs, &numdcs );
+
+ if (name_type == KDC_NAME_TYPE) {
+ status = ads_dns_query_kdcs(ctx, name, sitename, &dcs, &numdcs);
+ } else {
+ status = ads_dns_query_dcs(ctx, name, sitename, &dcs, &numdcs);
+ }
if ( !NT_STATUS_IS_OK( status ) ) {
talloc_destroy(ctx);
return False;
@@ -1114,6 +1146,7 @@ static BOOL resolve_ads(const char *name, int name_type,
**********************************************************************/
BOOL internal_resolve_name(const char *name, int name_type,
+ const char *sitename,
struct ip_service **return_iplist,
int *return_count, const char *resolve_order)
{
@@ -1129,7 +1162,8 @@ BOOL internal_resolve_name(const char *name, int name_type,
*return_iplist = NULL;
*return_count = 0;
- DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
+ DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
+ name, name_type, sitename ? sitename : NULL));
if (allzeros || allones || is_address) {
@@ -1189,10 +1223,19 @@ BOOL internal_resolve_name(const char *name, int name_type,
result = True;
goto done;
}
+ } else if(strequal( tok, "kdc")) {
+ /* deal with KDC_NAME_TYPE names here. This will result in a
+ SRV record lookup */
+ if (resolve_ads(name, KDC_NAME_TYPE, sitename, return_iplist, return_count)) {
+ result = True;
+ /* Ensure we don't namecache this with the KDC port. */
+ name_type = KDC_NAME_TYPE;
+ goto done;
+ }
} else if(strequal( tok, "ads")) {
/* deal with 0x1c names here. This will result in a
SRV record lookup */
- if (resolve_ads(name, name_type, return_iplist, return_count)) {
+ if (resolve_ads(name, name_type, sitename, return_iplist, return_count)) {
result = True;
goto done;
}
@@ -1268,14 +1311,16 @@ BOOL internal_resolve_name(const char *name, int name_type,
BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
{
struct ip_service *ip_list = NULL;
+ char *sitename = sitename_fetch(lp_realm()); /* wild guess */
int count = 0;
if (is_ipaddress(name)) {
*return_ip = *interpret_addr2(name);
+ SAFE_FREE(sitename);
return True;
}
- if (internal_resolve_name(name, name_type, &ip_list, &count, lp_name_resolve_order())) {
+ if (internal_resolve_name(name, name_type, sitename, &ip_list, &count, lp_name_resolve_order())) {
int i;
/* only return valid addresses for TCP connections */
@@ -1287,12 +1332,14 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
{
*return_ip = ip_list[i].ip;
SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
return True;
}
}
}
SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
return False;
}
@@ -1310,12 +1357,12 @@ BOOL find_master_ip(const char *group, struct in_addr *master_ip)
return False;
}
- if (internal_resolve_name(group, 0x1D, &ip_list, &count, lp_name_resolve_order())) {
+ if (internal_resolve_name(group, 0x1D, NULL, &ip_list, &count, lp_name_resolve_order())) {
*master_ip = ip_list[0].ip;
SAFE_FREE(ip_list);
return True;
}
- if(internal_resolve_name(group, 0x1B, &ip_list, &count, lp_name_resolve_order())) {
+ if(internal_resolve_name(group, 0x1B, NULL, &ip_list, &count, lp_name_resolve_order())) {
*master_ip = ip_list[0].ip;
SAFE_FREE(ip_list);
return True;
@@ -1332,12 +1379,12 @@ BOOL find_master_ip(const char *group, struct in_addr *master_ip)
BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
{
- struct ip_service *ip_list;
- int count;
+ struct ip_service *ip_list = NULL;
+ int count = 0;
/* Look up #1B name */
- if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) {
+ if (!internal_resolve_name(domain, 0x1b, NULL, &ip_list, &count, lp_name_resolve_order())) {
return False;
}
@@ -1356,13 +1403,17 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
return True;
}
+/* Private enum type for lookups. */
+
+enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
+
/********************************************************
Get the IP address list of the domain controllers for
a domain.
*********************************************************/
-static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
- int *count, BOOL ads_only, int *ordered)
+static NTSTATUS get_dc_list(const char *domain, const char *sitename, struct ip_service **ip_list,
+ int *count, enum dc_lookup_type lookup_type, int *ordered)
{
fstring resolve_order;
char *saf_servername;
@@ -1388,7 +1439,7 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
fstrcpy( resolve_order, lp_name_resolve_order() );
strlower_m( resolve_order );
- if ( ads_only ) {
+ if ( lookup_type == DC_ADS_ONLY) {
if ( strstr( resolve_order, "host" ) ) {
fstrcpy( resolve_order, "ads" );
@@ -1398,12 +1449,17 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
} else {
fstrcpy( resolve_order, "NULL" );
}
+ } else if (lookup_type == DC_KDC_ONLY) {
+ /* DNS SRV lookups used by the ads/kdc resolver
+ are already sorted by priority and weight */
+ *ordered = True;
+ fstrcpy( resolve_order, "kdc" );
}
/* fetch the server we have affinity for. Add the
'password server' list to a search for our domain controllers */
- saf_servername = saf_fetch( domain );
+ saf_servername = saf_fetch( domain);
if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
pstr_sprintf( pserver, "%s, %s",
@@ -1420,7 +1476,14 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
if ( !*pserver ) {
DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
- return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
+ /* TODO: change return type of internal_resolve_name to
+ * NTSTATUS */
+ if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
+ resolve_order)) {
+ return NT_STATUS_OK;
+ } else {
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
}
DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
@@ -1435,7 +1498,8 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
p = pserver;
while (next_token(&p,name,LIST_SEP,sizeof(name))) {
if (strequal(name, "*")) {
- if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count, resolve_order) )
+ if (internal_resolve_name(domain, 0x1C, sitename, &auto_ip_list,
+ &auto_count, resolve_order))
num_addresses += auto_count;
done_auto_lookup = True;
DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
@@ -1448,17 +1512,23 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
just return the list of DC's. Or maybe we just failed. */
if ( (num_addresses == 0) ) {
- if ( !done_auto_lookup ) {
- return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
- } else {
+ if ( done_auto_lookup ) {
DEBUG(4,("get_dc_list: no servers found\n"));
- return False;
+ SAFE_FREE(auto_ip_list);
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+ if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
+ resolve_order)) {
+ return NT_STATUS_OK;
+ } else {
+ return NT_STATUS_NO_LOGON_SERVERS;
}
}
if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
DEBUG(3,("get_dc_list: malloc fail !\n"));
- return False;
+ SAFE_FREE(auto_ip_list);
+ return NT_STATUS_NO_MEMORY;
}
p = pserver;
@@ -1536,22 +1606,32 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
*ip_list = return_iplist;
*count = local_count;
- return (*count != 0);
+ return ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
}
/*********************************************************************
Small wrapper function to get the DC list and sort it if neccessary.
*********************************************************************/
-BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
+NTSTATUS get_sorted_dc_list( const char *domain, const char *sitename, struct ip_service **ip_list, int *count, BOOL ads_only )
{
BOOL ordered;
-
- DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
+ NTSTATUS status;
+ enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
+
+ DEBUG(8,("get_sorted_dc_list: attempting lookup for name %s (sitename %s) "
+ "using [%s]\n",
+ domain,
+ sitename ? sitename : "NULL",
(ads_only ? "ads" : lp_name_resolve_order())));
- if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) ) {
- return False;
+ if (ads_only) {
+ lookup_type = DC_ADS_ONLY;
+ }
+
+ status = get_dc_list(domain, sitename, ip_list, count, lookup_type, &ordered);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* only sort if we don't already have an ordered list */
@@ -1559,5 +1639,31 @@ BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *c
sort_ip_list2( *ip_list, *count );
}
- return True;
+ return NT_STATUS_OK;
+}
+
+/*********************************************************************
+ Get the KDC list - re-use all the logic in get_dc_list.
+*********************************************************************/
+
+NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_service **ip_list, int *count)
+{
+ BOOL ordered;
+ NTSTATUS status;
+
+ *count = 0;
+ *ip_list = NULL;
+
+ status = get_dc_list(realm, sitename, ip_list, count, DC_KDC_ONLY, &ordered);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* only sort if we don't already have an ordered list */
+ if ( !ordered ) {
+ sort_ip_list2( *ip_list, *count );
+ }
+
+ return NT_STATUS_OK;
}
diff --git a/source/libsmb/namequery_dc.c b/source/libsmb/namequery_dc.c
index b9a593bf2a7..110b9986b7f 100644
--- a/source/libsmb/namequery_dc.c
+++ b/source/libsmb/namequery_dc.c
@@ -25,35 +25,103 @@
#include "includes.h"
+/**********************************************************************
+ Is this our primary domain ?
+**********************************************************************/
+
+#ifdef HAVE_KRB5
+static BOOL is_our_primary_domain(const char *domain)
+{
+ int role = lp_server_role();
+
+ if ((role == ROLE_DOMAIN_MEMBER) && strequal(lp_workgroup(), domain)) {
+ return True;
+ } else if (strequal(get_global_sam_name(), domain)) {
+ return True;
+ }
+ return False;
+}
+#endif
+
/**************************************************************************
- Find the name and IP address for a server in he realm/domain
+ Find the name and IP address for a server in the realm/domain
*************************************************************************/
-static BOOL ads_dc_name(const char *domain, const char *realm, struct in_addr *dc_ip, fstring srv_name)
+static BOOL ads_dc_name(const char *domain,
+ const char *realm,
+ struct in_addr *dc_ip,
+ fstring srv_name)
{
ADS_STRUCT *ads;
+ char *sitename;
+ int i;
- if (!realm && strequal(domain, lp_workgroup()))
+ if (!realm && strequal(domain, lp_workgroup())) {
realm = lp_realm();
+ }
- ads = ads_init(realm, domain, NULL);
- if (!ads)
- return False;
+ sitename = sitename_fetch(realm);
+
+ /* Try this 3 times then give up. */
+ for( i =0 ; i < 3; i++) {
+ ads = ads_init(realm, domain, NULL);
+ if (!ads) {
+ SAFE_FREE(sitename);
+ return False;
+ }
- DEBUG(4,("ads_dc_name: domain=%s\n", domain));
+ DEBUG(4,("ads_dc_name: domain=%s\n", domain));
#ifdef HAVE_ADS
- /* we don't need to bind, just connect */
- ads->auth.flags |= ADS_AUTH_NO_BIND;
+ /* we don't need to bind, just connect */
+ ads->auth.flags |= ADS_AUTH_NO_BIND;
+ ads_connect(ads);
+#endif
+
+ if (!ads->config.realm) {
+ SAFE_FREE(sitename);
+ ads_destroy(&ads);
+ return False;
+ }
+
+ /* Now we've found a server, see if our sitename
+ has changed. If so, we need to re-do the DNS query
+ to ensure we only find servers in our site. */
+
+ if (stored_sitename_changed(realm, sitename)) {
+ SAFE_FREE(sitename);
+ sitename = sitename_fetch(realm);
+ ads_destroy(&ads);
+ /* Ensure we don't cache the DC we just connected to. */
+ namecache_delete(realm, 0x1C);
+ namecache_delete(domain, 0x1C);
+ continue;
+ }
+
+#ifdef HAVE_KRB5
+ if (is_our_primary_domain(domain) && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
+ /* We're going to use this KDC for this realm/domain.
+ If we are using sites, then force the krb5 libs
+ to use this KDC. */
- ads_connect(ads);
+ create_local_private_krb5_conf_for_domain(realm,
+ domain,
+ sitename,
+ ads->ldap_ip);
+ }
#endif
+ break;
+ }
- if (!ads->config.realm) {
- ads_destroy(&ads);
+ if (i == 3) {
+ DEBUG(1,("ads_dc_name: sitename (now \"%s\") keeps changing ???\n",
+ sitename ? sitename : ""));
+ SAFE_FREE(sitename);
return False;
}
+ SAFE_FREE(sitename);
+
fstrcpy(srv_name, ads->config.ldap_server_name);
strupper_m(srv_name);
*dc_ip = ads->ldap_ip;
@@ -81,7 +149,8 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip
/* get a list of all domain controllers */
- if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
+ if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, NULL, &ip_list, &count,
+ False))) {
DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
return False;
}
@@ -156,4 +225,3 @@ BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct
return ret;
}
-
diff --git a/source/libsmb/nterr.c b/source/libsmb/nterr.c
index 4f97379ee07..35ebc3d3397 100644
--- a/source/libsmb/nterr.c
+++ b/source/libsmb/nterr.c
@@ -22,13 +22,13 @@
#include "includes.h"
-typedef const struct
+typedef struct
{
const char *nt_errstr;
NTSTATUS nt_errcode;
} nt_err_code_struct;
-static nt_err_code_struct nt_errs[] =
+static const nt_err_code_struct nt_errs[] =
{
{ "NT_STATUS_OK", NT_STATUS_OK },
{ "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
@@ -533,6 +533,7 @@ static nt_err_code_struct nt_errs[] =
{ "NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS },
{ "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT },
{ "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE },
+ { "NT_STATUS_DS_NO_MORE_RIDS", NT_STATUS_DS_NO_MORE_RIDS },
{ "NT_STATUS_NOT_A_REPARSE_POINT", NT_STATUS_NOT_A_REPARSE_POINT },
{ "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
{ "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
@@ -569,10 +570,8 @@ nt_err_code_struct nt_err_desc[] =
{ "Invalid workstation", NT_STATUS_INVALID_WORKSTATION },
{ "Password expired", NT_STATUS_PASSWORD_EXPIRED },
{ "Account disabled", NT_STATUS_ACCOUNT_DISABLED },
- { "Unexpected information received", NT_STATUS_INVALID_PARAMETER },
{ "Memory allocation error", NT_STATUS_NO_MEMORY },
{ "No domain controllers located", NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND },
- { "Account locked out", NT_STATUS_ACCOUNT_LOCKED_OUT },
{ "Named pipe not available", NT_STATUS_PIPE_NOT_AVAILABLE },
{ "Not implemented", NT_STATUS_NOT_IMPLEMENTED },
{ "Invalid information class", NT_STATUS_INVALID_INFO_CLASS },
@@ -583,7 +582,6 @@ nt_err_code_struct nt_err_desc[] =
{ "No memory", NT_STATUS_NO_MEMORY },
{ "Buffer too small", NT_STATUS_BUFFER_TOO_SMALL },
{ "Revision mismatch", NT_STATUS_REVISION_MISMATCH },
- { "No logon servers", NT_STATUS_NO_LOGON_SERVERS },
{ "No such logon session", NT_STATUS_NO_SUCH_LOGON_SESSION },
{ "No such privilege", NT_STATUS_NO_SUCH_PRIVILEGE },
{ "Procedure not found", NT_STATUS_PROCEDURE_NOT_FOUND },
@@ -653,11 +651,16 @@ const char *nt_errstr(NTSTATUS nt_code)
static pstring msg;
int idx = 0;
+#ifdef HAVE_LDAP
+ if (NT_STATUS_TYPE(nt_code) == NT_STATUS_TYPE_LDAP) {
+ return ldap_err2string(NT_STATUS_LDAP_CODE(nt_code));
+ }
+#endif
+
slprintf(msg, sizeof(msg), "NT code 0x%08x", NT_STATUS_V(nt_code));
while (nt_errs[idx].nt_errstr != NULL) {
- if (NT_STATUS_V(nt_errs[idx].nt_errcode) ==
- NT_STATUS_V(nt_code)) {
+ if (NT_STATUS_EQUAL(nt_errs[idx].nt_errcode, nt_code)) {
return nt_errs[idx].nt_errstr;
}
idx++;
diff --git a/source/libsmb/ntlm_check.c b/source/libsmb/ntlm_check.c
index 212bc19767d..e1fc92e3449 100644
--- a/source/libsmb/ntlm_check.c
+++ b/source/libsmb/ntlm_check.c
@@ -183,7 +183,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
DATA_BLOB *user_sess_key,
DATA_BLOB *lm_sess_key)
{
- static const unsigned char zeros[8];
+ static const unsigned char zeros[8] = { 0, };
if (nt_pw == NULL) {
DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n",
username));
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index 78292ed56f0..2f919b3f766 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -155,18 +155,41 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
}
/**
- * Set a password on an NTLMSSP context - ensures it is talloc()ed
+ * Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed
+ *
+ */
+NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state,
+ const unsigned char lm_hash[16],
+ const unsigned char nt_hash[16])
+{
+ ntlmssp_state->lm_hash = (unsigned char *)
+ TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16);
+ ntlmssp_state->nt_hash = (unsigned char *)
+ TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16);
+ if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) {
+ TALLOC_FREE(ntlmssp_state->lm_hash);
+ TALLOC_FREE(ntlmssp_state->nt_hash);
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+/**
+ * Converts a password to the hashes on an NTLMSSP context.
*
*/
NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password)
{
if (!password) {
- ntlmssp_state->password = NULL;
+ ntlmssp_state->lm_hash = NULL;
+ ntlmssp_state->nt_hash = NULL;
} else {
- ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
- if (!ntlmssp_state->password) {
- return NT_STATUS_NO_MEMORY;
- }
+ unsigned char lm_hash[16];
+ unsigned char nt_hash[16];
+
+ E_deshash(password, lm_hash);
+ E_md4hash(password, nt_hash);
+ return ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);
}
return NT_STATUS_OK;
}
@@ -211,6 +234,50 @@ NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state,
}
/**
+ * Request features for the NTLMSSP negotiation
+ *
+ * @param ntlmssp_state NTLMSSP state
+ * @param feature_list List of space seperated features requested from NTLMSSP.
+ */
+void ntlmssp_want_feature_list(NTLMSSP_STATE *ntlmssp_state, char *feature_list)
+{
+ /*
+ * We need to set this to allow a later SetPassword
+ * via the SAMR pipe to succeed. Strange.... We could
+ * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
+ */
+ if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+ }
+}
+
+/**
+ * Request a feature for the NTLMSSP negotiation
+ *
+ * @param ntlmssp_state NTLMSSP state
+ * @param feature Bit flag specifying the requested feature
+ */
+void ntlmssp_want_feature(NTLMSSP_STATE *ntlmssp_state, uint32 feature)
+{
+ /* As per JRA's comment above */
+ if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (feature & NTLMSSP_FEATURE_SIGN) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (feature & NTLMSSP_FEATURE_SEAL) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+ }
+}
+
+/**
* Next state function for the NTLMSSP state machine
*
* @param ntlmssp_state NTLMSSP State
@@ -353,8 +420,8 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
}
- if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) {
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
}
if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
@@ -861,6 +928,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_56 |
NTLMSSP_UNKNOWN_02000000 |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
NTLMSSP_NEGOTIATE_NTLM |
NTLMSSP_NEGOTIATE_NTLM2 |
NTLMSSP_NEGOTIATE_KEY_EXCH |
@@ -994,8 +1062,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
return NT_STATUS_INVALID_PARAMETER;
}
- if (!ntlmssp_state->password) {
- static const uchar zeros[16];
+ if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
+ static const uchar zeros[16] = { 0, };
/* do nothing - blobs are zero length */
/* session key is all zeros */
@@ -1014,9 +1082,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
/* TODO: if the remote server is standalone, then we should replace 'domain'
with the server name as supplied above */
- if (!SMBNTLMv2encrypt(ntlmssp_state->user,
+ if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user,
ntlmssp_state->domain,
- ntlmssp_state->password, &challenge_blob,
+ ntlmssp_state->nt_hash, &challenge_blob,
&struct_blob,
&lm_response, &nt_response, &session_key)) {
data_blob_free(&challenge_blob);
@@ -1025,11 +1093,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
}
} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
struct MD5Context md5_session_nonce_ctx;
- uchar nt_hash[16];
uchar session_nonce[16];
uchar session_nonce_hash[16];
uchar user_session_key[16];
- E_md4hash(ntlmssp_state->password, nt_hash);
lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
generate_random_buffer(lm_response.data, 8);
@@ -1048,40 +1114,35 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
dump_data(5, (const char *)session_nonce_hash, 8);
nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
- SMBNTencrypt(ntlmssp_state->password,
+ SMBNTencrypt_hash(ntlmssp_state->nt_hash,
session_nonce_hash,
nt_response.data);
session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
- SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key);
+ SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key);
hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
} else {
- uchar lm_hash[16];
- uchar nt_hash[16];
- E_deshash(ntlmssp_state->password, lm_hash);
- E_md4hash(ntlmssp_state->password, nt_hash);
-
/* lanman auth is insecure, it may be disabled */
if (lp_client_lanman_auth()) {
lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
- SMBencrypt(ntlmssp_state->password,challenge_blob.data,
+ SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
lm_response.data);
}
nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
- SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
+ SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
nt_response.data);
session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
&& lp_client_lanman_auth()) {
- SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data,
+ SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
session_key.data);
dump_data_pw("LM session key\n", session_key.data, session_key.length);
} else {
- SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+ SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data);
dump_data_pw("NT session key:\n", session_key.data, session_key.length);
}
}
@@ -1169,15 +1230,10 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
NTLMSSP_NEGOTIATE_NTLM |
NTLMSSP_NEGOTIATE_NTLM2 |
NTLMSSP_NEGOTIATE_KEY_EXCH |
- /*
- * We need to set this to allow a later SetPassword
- * via the SAMR pipe to succeed. Strange.... We could
- * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
- * */
- NTLMSSP_NEGOTIATE_SIGN |
NTLMSSP_REQUEST_TARGET;
return NT_STATUS_OK;
diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c
index 10921d56e71..5642be42a3d 100644
--- a/source/libsmb/ntlmssp_sign.c
+++ b/source/libsmb/ntlmssp_sign.c
@@ -307,7 +307,7 @@ NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
return NT_STATUS_NO_USER_SESSION_KEY;
}
- DEBUG(10,("ntlmssp_unseal_data: seal\n"));
+ DEBUG(10,("ntlmssp_unseal_packet: seal\n"));
dump_data_pw("ntlmssp sealed data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
diff --git a/source/libsmb/passchange.c b/source/libsmb/passchange.c
index 90eb67aceaa..5b4b0896c0f 100644
--- a/source/libsmb/passchange.c
+++ b/source/libsmb/passchange.c
@@ -29,7 +29,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
char *err_str, size_t err_str_len)
{
struct nmb_name calling, called;
- struct cli_state cli;
+ struct cli_state *cli;
struct rpc_pipe_client *pipe_hnd;
struct in_addr ip;
@@ -44,91 +44,96 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
return NT_STATUS_UNSUCCESSFUL;
}
- ZERO_STRUCT(cli);
-
- if (!cli_initialise(&cli) || !cli_connect(&cli, remote_machine, &ip)) {
+ cli = cli_initialise();
+ if (!cli) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!cli_connect(cli, remote_machine, &ip)) {
slprintf(err_str, err_str_len-1, "unable to connect to SMB server on machine %s. Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- return NT_STATUS_UNSUCCESSFUL;
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
+ return result;
}
make_nmb_name(&calling, global_myname() , 0x0);
make_nmb_name(&called , remote_machine, 0x20);
- if (!cli_session_request(&cli, &calling, &called)) {
+ if (!cli_session_request(cli, &calling, &called)) {
slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- cli_shutdown(&cli);
- return NT_STATUS_UNSUCCESSFUL;
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
+ return result;
}
- cli.protocol = PROTOCOL_NT1;
+ cli->protocol = PROTOCOL_NT1;
- if (!cli_negprot(&cli)) {
+ if (!cli_negprot(cli)) {
slprintf(err_str, err_str_len-1, "machine %s rejected the negotiate protocol. Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
return result;
}
/* Given things like SMB signing, restrict anonymous and the like,
try an authenticated connection first */
- if (!cli_session_setup(&cli, user_name, old_passwd, strlen(old_passwd)+1, old_passwd, strlen(old_passwd)+1, "")) {
-
- result = cli_nt_error(&cli);
-
- if (!NT_STATUS_IS_OK(result)) {
-
- /* Password must change or Password expired are the only valid
- * error conditions here from where we can proceed, the rest like
- * account locked out or logon failure will lead to errors later
- * anyway */
-
- if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
- !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
-
- slprintf(err_str, err_str_len-1, "Could not "
- "connect to machine %s: %s\n",
- remote_machine, cli_errstr(&cli));
- cli_shutdown(&cli);
- return result;
- }
-
- pass_must_change = True;
+ result = cli_session_setup(cli, user_name,
+ old_passwd, strlen(old_passwd)+1,
+ old_passwd, strlen(old_passwd)+1, "");
+
+ if (!NT_STATUS_IS_OK(result)) {
+
+ /* Password must change or Password expired are the only valid
+ * error conditions here from where we can proceed, the rest like
+ * account locked out or logon failure will lead to errors later
+ * anyway */
+
+ if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
+ slprintf(err_str, err_str_len-1, "Could not "
+ "connect to machine %s: %s\n",
+ remote_machine, cli_errstr(cli));
+ cli_shutdown(cli);
+ return result;
}
+ pass_must_change = True;
+
/*
* We should connect as the anonymous user here, in case
* the server has "must change password" checked...
* Thanks to <Nicholas.S.Jenkins@cdc.com> for this fix.
*/
- if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
+ result = cli_session_setup(cli, "", "", 0, "", 0, "");
+
+ if (!NT_STATUS_IS_OK(result)) {
slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ remote_machine, cli_errstr(cli) );
+ cli_shutdown(cli);
return result;
}
- cli_init_creds(&cli, "", "", NULL);
+ cli_init_creds(cli, "", "", NULL);
} else {
- cli_init_creds(&cli, user_name, "", old_passwd);
+ cli_init_creds(cli, user_name, "", old_passwd);
}
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
+ if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
slprintf(err_str, err_str_len-1, "machine %s rejected the tconX on the IPC$ share. Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
return result;
}
/* Try not to give the password away too easily */
if (!pass_must_change) {
- pipe_hnd = cli_rpc_pipe_open_ntlmssp(&cli,
+ pipe_hnd = cli_rpc_pipe_open_ntlmssp(cli,
PI_SAMR,
PIPE_AUTH_LEVEL_PRIVACY,
"", /* what domain... ? */
@@ -144,17 +149,17 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
* will just fail. So we do it anonymously, there's no other
* way.
*/
- pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result);
+ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
}
if (!pipe_hnd) {
if (lp_client_lanman_auth()) {
/* Use the old RAP method. */
- if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
+ if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
return result;
}
} else {
@@ -162,16 +167,16 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
"SAMR connection to machine %s failed. Error was %s, "
"but LANMAN password changed are disabled\n",
nt_errstr(result), remote_machine);
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
return result;
}
}
- if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli.mem_ctx, user_name,
+ if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli->mem_ctx, user_name,
new_passwd, old_passwd))) {
/* Great - it all worked! */
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return NT_STATUS_OK;
} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)
@@ -180,7 +185,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
remote_machine, get_friendly_nt_error_msg(result));
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return result;
}
@@ -188,21 +193,21 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
cli_rpc_pipe_close(pipe_hnd);
/* Try anonymous NTLMSSP... */
- cli_init_creds(&cli, "", "", NULL);
+ cli_init_creds(cli, "", "", NULL);
result = NT_STATUS_UNSUCCESSFUL;
/* OK, this is ugly, but... try an anonymous pipe. */
- pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result);
+ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
if ( pipe_hnd &&
(NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd,
- cli.mem_ctx,
+ cli->mem_ctx,
user_name,
new_passwd,
old_passwd)))) {
/* Great - it all worked! */
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return NT_STATUS_OK;
} else {
if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)
@@ -212,7 +217,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
slprintf(err_str, err_str_len-1,
"machine %s rejected the (anonymous) password change: Error was : %s.\n",
remote_machine, get_friendly_nt_error_msg(result));
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return result;
}
@@ -221,24 +226,24 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
if (lp_client_lanman_auth()) {
/* Use the old RAP method. */
- if (cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
+ if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
/* SAMR failed, but the old LanMan protocol worked! */
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return NT_STATUS_OK;
}
slprintf(err_str, err_str_len-1,
"machine %s rejected the password change: Error was : %s.\n",
- remote_machine, cli_errstr(&cli) );
- result = cli_nt_error(&cli);
- cli_shutdown(&cli);
+ remote_machine, cli_errstr(cli) );
+ result = cli_nt_error(cli);
+ cli_shutdown(cli);
return result;
} else {
slprintf(err_str, err_str_len-1,
"SAMR connection to machine %s failed. Error was %s, "
"but LANMAN password changed are disabled\n",
nt_errstr(result), remote_machine);
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return NT_STATUS_UNSUCCESSFUL;
}
}
diff --git a/source/libsmb/samlogon_cache.c b/source/libsmb/samlogon_cache.c
index 7a6d9a96ad0..b242d0ef55b 100644
--- a/source/libsmb/samlogon_cache.c
+++ b/source/libsmb/samlogon_cache.c
@@ -67,7 +67,8 @@ void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
winbindd_cache.tdb open. Open the tdb if a NULL is passed. */
if (!tdb) {
- tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
TDB_DEFAULT, O_RDWR, 0600);
if (!tdb) {
DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
diff --git a/source/libsmb/smb_share_modes.c b/source/libsmb/smb_share_modes.c
index 34ede9df296..4c49ecb7bd9 100644
--- a/source/libsmb/smb_share_modes.c
+++ b/source/libsmb/smb_share_modes.c
@@ -33,6 +33,10 @@
#undef malloc
#endif
+int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, uint64_t dev,
+ uint64_t ino, const struct smb_share_mode_entry *new_entry,
+ const char *sharepath, const char *filename);
+
static BOOL sharemodes_procid_equal(const struct process_id *p1, const struct process_id *p2)
{
return (p1->pid == p2->pid);
@@ -150,6 +154,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
out->dev = (SMB_DEV_T)in->dev;
out->inode = (SMB_INO_T)in->ino;
out->uid = (uint32)geteuid();
+ out->flags = 0;
}
/*
@@ -259,9 +264,10 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
if (!db_data.dptr) {
/* We must create the entry. */
- db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) +
- strlen(sharepath) + 1 +
- strlen(filename) + 1);
+ db_data.dptr = (char *)malloc(
+ (2*sizeof(struct share_mode_entry)) +
+ strlen(sharepath) + 1 +
+ strlen(filename) + 1);
if (!db_data.dptr) {
return -1;
}
@@ -269,7 +275,6 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
memset(ld, '\0', sizeof(struct locking_data));
ld->u.s.num_share_mode_entries = 1;
ld->u.s.delete_on_close = 0;
- ld->u.s.initial_delete_on_close = 0;
ld->u.s.delete_token_size = 0;
shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
create_share_mode_entry(shares, new_entry);
@@ -294,7 +299,8 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
}
/* Entry exists, we must add a new entry. */
- new_data_p = malloc(db_data.dsize + sizeof(struct share_mode_entry));
+ new_data_p = (char *)malloc(
+ db_data.dsize + sizeof(struct share_mode_entry));
if (!new_data_p) {
free(db_data.dptr);
return -1;
@@ -391,7 +397,8 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
}
/* More than one - allocate a new record minus the one we'll delete. */
- new_data_p = malloc(db_data.dsize - sizeof(struct share_mode_entry));
+ new_data_p = (char *)malloc(
+ db_data.dsize - sizeof(struct share_mode_entry));
if (!new_data_p) {
free(db_data.dptr);
return -1;
diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c
index e59254b16f3..df74b2db36a 100644
--- a/source/libsmb/smb_signing.c
+++ b/source/libsmb/smb_signing.c
@@ -327,7 +327,8 @@ static void simple_packet_signature(struct smb_basic_signing_context *data,
static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
unsigned char calc_md5_mac[16];
- struct smb_basic_signing_context *data = si->signing_context;
+ struct smb_basic_signing_context *data =
+ (struct smb_basic_signing_context *)si->signing_context;
if (!si->doing_signing)
return;
@@ -382,7 +383,8 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
unsigned char calc_md5_mac[16];
unsigned char *server_sent_mac;
- struct smb_basic_signing_context *data = si->signing_context;
+ struct smb_basic_signing_context *data =
+ (struct smb_basic_signing_context *)si->signing_context;
if (!si->doing_signing)
return True;
@@ -437,7 +439,8 @@ We were expecting seq %u\n", reply_seq_number+i, reply_seq_number ));
static void simple_free_signing_context(struct smb_sign_info *si)
{
- struct smb_basic_signing_context *data = si->signing_context;
+ struct smb_basic_signing_context *data =
+ (struct smb_basic_signing_context *)si->signing_context;
struct outstanding_packet_lookup *list;
struct outstanding_packet_lookup *next;
@@ -661,7 +664,8 @@ BOOL client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid)
static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
unsigned char calc_md5_mac[16];
- struct smb_basic_signing_context *data = si->signing_context;
+ struct smb_basic_signing_context *data =
+ (struct smb_basic_signing_context *)si->signing_context;
uint32 send_seq_number = data->send_seq_num-1;
uint16 mid;
@@ -702,7 +706,8 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
{
BOOL good;
- struct smb_basic_signing_context *data = si->signing_context;
+ struct smb_basic_signing_context *data =
+ (struct smb_basic_signing_context *)si->signing_context;
uint32 reply_seq_number = data->send_seq_num;
uint32 saved_seq;
unsigned char calc_md5_mac[16];
diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c
index ee43f4beee5..8168eee207f 100644
--- a/source/libsmb/smbdes.c
+++ b/source/libsmb/smbdes.c
@@ -172,7 +172,7 @@ static void concat(char *out, char *in1, char *in2, int l1, int l2)
*out++ = *in2++;
}
-static void xor(char *out, char *in1, char *in2, int n)
+static void x_or(char *out, char *in1, char *in2, int n)
{
int i;
for (i=0;i<n;i++)
@@ -223,7 +223,7 @@ static void dohash(char *out, char *in, char *key, int forw)
permute(er, r, perm4, 48);
- xor(erk, er, ki[forw ? i : 15 - i], 48);
+ x_or(erk, er, ki[forw ? i : 15 - i], 48);
for (j=0;j<8;j++)
for (k=0;k<6;k++)
@@ -244,7 +244,7 @@ static void dohash(char *out, char *in, char *key, int forw)
cb[j*4+k] = b[j][k];
permute(pcb, cb, perm5, 32);
- xor(r2, l, pcb, 32);
+ x_or(r2, l, pcb, 32);
for (j=0;j<32;j++)
l[j] = r[j];
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index f285cdd3084..5f7b5b18093 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -25,30 +25,38 @@
#include "includes.h"
#include "byteorder.h"
-/*
- This implements the X/Open SMB password encryption
- It takes a password ('unix' string), a 8 byte "crypt key"
- and puts 24 bytes of encrypted password into p24
-
- Returns False if password must have been truncated to create LM hash
-*/
-BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
+void SMBencrypt_hash(const uchar lm_hash[16], const uchar *c8, uchar p24[24])
{
- BOOL ret;
uchar p21[21];
memset(p21,'\0',21);
- ret = E_deshash(passwd, p21);
+ memcpy(p21, lm_hash, 16);
SMBOWFencrypt(p21, c8, p24);
#ifdef DEBUG_PASSWORD
- DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
+ DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n"));
dump_data(100, (const char *)p21, 16);
dump_data(100, (const char *)c8, 8);
dump_data(100, (const char *)p24, 24);
#endif
+}
+/*
+ This implements the X/Open SMB password encryption
+ It takes a password ('unix' string), a 8 byte "crypt key"
+ and puts 24 bytes of encrypted password into p24
+
+ Returns False if password must have been truncated to create LM hash
+*/
+
+BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
+{
+ BOOL ret;
+ uchar lm_hash[16];
+
+ ret = E_deshash(passwd, lm_hash);
+ SMBencrypt_hash(lm_hash, c8, p24);
return ret;
}
@@ -237,15 +245,14 @@ void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p
}
-/* Does the NT MD4 hash then des encryption. */
+/* Does the des encryption. */
-void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
+void SMBNTencrypt_hash(const uchar nt_hash[16], uchar *c8, uchar *p24)
{
uchar p21[21];
memset(p21,'\0',21);
-
- E_md4hash(passwd, p21);
+ memcpy(p21, nt_hash, 16);
SMBOWFencrypt(p21, c8, p24);
#ifdef DEBUG_PASSWORD
@@ -256,6 +263,15 @@ void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
#endif
}
+/* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
+
+void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
+{
+ uchar nt_hash[16];
+ E_md4hash(passwd, nt_hash);
+ SMBNTencrypt_hash(nt_hash, c8, p24);
+}
+
/* Does the md5 encryption from the Key Response for NTLMv2. */
void SMBOWFencrypt_ntv2(const uchar kr[16],
const DATA_BLOB *srv_chal,
@@ -416,15 +432,13 @@ static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16],
return final_response;
}
-BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
+BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_hash[16],
const DATA_BLOB *server_chal,
const DATA_BLOB *names_blob,
DATA_BLOB *lm_response, DATA_BLOB *nt_response,
DATA_BLOB *user_session_key)
{
- uchar nt_hash[16];
uchar ntlm_v2_hash[16];
- E_md4hash(password, nt_hash);
/* We don't use the NT# directly. Instead we use it mashed up with
the username and domain.
@@ -455,6 +469,24 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
return True;
}
+/* Plaintext version of the above. */
+
+BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
+ const DATA_BLOB *server_chal,
+ const DATA_BLOB *names_blob,
+ DATA_BLOB *lm_response, DATA_BLOB *nt_response,
+ DATA_BLOB *user_session_key)
+{
+ uchar nt_hash[16];
+ E_md4hash(password, nt_hash);
+
+ return SMBNTLMv2encrypt_hash(user, domain, nt_hash,
+ server_chal,
+ names_blob,
+ lm_response, nt_response,
+ user_session_key);
+}
+
/***********************************************************
encode a password buffer with a unicode password. The buffer
is filled with random data to make it harder to attack.
diff --git a/source/libsmb/trustdom_cache.c b/source/libsmb/trustdom_cache.c
index 8c5fb4d9071..dc0b5010a27 100644
--- a/source/libsmb/trustdom_cache.c
+++ b/source/libsmb/trustdom_cache.c
@@ -183,7 +183,6 @@ BOOL trustdom_cache_fetch(const char* name, DOM_SID* sid)
if (!gencache_get(key, &value, &timeout)) {
DEBUG(5, ("no entry for trusted domain %s found.\n", name));
SAFE_FREE(key);
- SAFE_FREE(value);
return False;
} else {
SAFE_FREE(key);
@@ -251,24 +250,6 @@ BOOL trustdom_cache_store_timestamp( uint32 t, time_t timeout )
}
-/*******************************************************************
- lock the timestamp entry in the trustdom_cache
-*******************************************************************/
-
-BOOL trustdom_cache_lock_timestamp( void )
-{
- return gencache_lock_entry( TDOMTSKEY ) != -1;
-}
-
-/*******************************************************************
- unlock the timestamp entry in the trustdom_cache
-*******************************************************************/
-
-void trustdom_cache_unlock_timestamp( void )
-{
- gencache_unlock_entry( TDOMTSKEY );
-}
-
/**
* Delete single trustdom entry. Look at the
* gencache_iterate definition.
@@ -315,8 +296,7 @@ void update_trustdom_cache( void )
time_t now = time(NULL);
int i;
- /* get the timestamp. We have to initialise it if the last timestamp == 0 */
-
+ /* get the timestamp. We have to initialise it if the last timestamp == 0 */
if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 )
trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL);
@@ -326,11 +306,12 @@ void update_trustdom_cache( void )
DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n"));
return;
}
+
+ /* note that we don't lock the timestamp. This prevents this
+ smbd from blocking all other smbd daemons while we
+ enumerate the trusted domains */
+ trustdom_cache_store_timestamp(now, now+TRUSTDOM_UPDATE_INTERVAL);
- /* lock the timestamp */
- if ( !trustdom_cache_lock_timestamp() )
- return;
-
if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) {
DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n"));
goto done;
@@ -339,20 +320,19 @@ void update_trustdom_cache( void )
/* get the domains and store them */
if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names,
- &num_domains, &dom_sids) )
- {
+ &num_domains, &dom_sids)) {
for ( i=0; i<num_domains; i++ ) {
trustdom_cache_store( domain_names[i], NULL, &dom_sids[i],
now+TRUSTDOM_UPDATE_INTERVAL);
- }
-
- trustdom_cache_store_timestamp( now, now+TRUSTDOM_UPDATE_INTERVAL );
+ }
+ } else {
+ /* we failed to fetch the list of trusted domains - restore the old
+ timestamp */
+ trustdom_cache_store_timestamp(last_check,
+ last_check+TRUSTDOM_UPDATE_INTERVAL);
}
done:
- /* unlock and we're done */
- trustdom_cache_unlock_timestamp();
-
talloc_destroy( mem_ctx );
return;
diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c
index 55108bf72f2..e4061883eb1 100644
--- a/source/libsmb/trusts_util.c
+++ b/source/libsmb/trusts_util.c
@@ -99,7 +99,7 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
- timestring(False)));
+ current_timestring(False)));
/*
* Return the result of trying to write the new password
* back into the trust account file.
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index 267a08d15fa..872ed2bbeaf 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -32,29 +32,6 @@
#define ZERO_ZERO 0
-/* This contains elements that differentiate locks. The smbpid is a
- client supplied pid, and is essentially the locking context for
- this client */
-
-struct lock_context {
- uint16 smbpid;
- uint16 tid;
- struct process_id pid;
-};
-
-/* The data in brlock records is an unsorted linear array of these
- records. It is unnecessary to store the count as tdb provides the
- size of the record */
-
-struct lock_struct {
- struct lock_context context;
- br_off start;
- br_off size;
- int fnum;
- enum brl_type lock_type;
- enum brl_flavour lock_flav;
-};
-
/* The open brlock.tdb database. */
static TDB_CONTEXT *tdb;
@@ -83,7 +60,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls)
See if two locking contexts are equal.
****************************************************************************/
-static BOOL brl_same_context(const struct lock_context *ctx1,
+BOOL brl_same_context(const struct lock_context *ctx1,
const struct lock_context *ctx2)
{
return (procid_equal(&ctx1->pid, &ctx2->pid) &&
@@ -121,7 +98,7 @@ static BOOL brl_conflict(const struct lock_struct *lck1,
const struct lock_struct *lck2)
{
/* Ignore PENDING locks. */
- if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
+ if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
return False;
/* Read locks never conflict. */
@@ -152,7 +129,7 @@ static BOOL brl_conflict_posix(const struct lock_struct *lck1,
#endif
/* Ignore PENDING locks. */
- if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
+ if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
return False;
/* Read locks never conflict. */
@@ -174,7 +151,7 @@ static BOOL brl_conflict_posix(const struct lock_struct *lck1,
static BOOL brl_conflict1(const struct lock_struct *lck1,
const struct lock_struct *lck2)
{
- if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
+ if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
return False;
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
@@ -207,7 +184,7 @@ static BOOL brl_conflict1(const struct lock_struct *lck1,
static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock_struct *lck2)
{
- if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
+ if (IS_PENDING_LOCK(lck1->lock_type) || IS_PENDING_LOCK(lck2->lock_type))
return False;
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK)
@@ -234,30 +211,47 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock
}
/****************************************************************************
- Amazingly enough, w2k3 "remembers" whether the last lock failure
+ Check if an unlock overlaps a pending lock.
+****************************************************************************/
+
+static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock)
+{
+ if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
+ return True;
+ if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
+ return True;
+ return False;
+}
+
+/****************************************************************************
+ Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum
is the same as this one and changes its error code. I wonder if any
app depends on this ?
****************************************************************************/
-static NTSTATUS brl_lock_failed(const struct lock_struct *lock)
+static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, BOOL blocking_lock)
{
- static struct lock_struct last_lock_failure;
-
- if (brl_same_context(&lock->context, &last_lock_failure.context) &&
- lock->fnum == last_lock_failure.fnum &&
- lock->start == last_lock_failure.start &&
- lock->size == last_lock_failure.size) {
- return NT_STATUS_FILE_LOCK_CONFLICT;
- }
- last_lock_failure = *lock;
- if (lock->start >= 0xEF000000 &&
- (lock->start >> 63) == 0) {
+ if (lock->start >= 0xEF000000 && (lock->start >> 63) == 0) {
/* amazing the little things you learn with a test
suite. Locks beyond this offset (as a 64 bit
number!) always generate the conflict error code,
unless the top bit is set */
+ if (!blocking_lock) {
+ fsp->last_lock_failure = *lock;
+ }
return NT_STATUS_FILE_LOCK_CONFLICT;
}
+
+ if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) &&
+ lock->context.tid == fsp->last_lock_failure.context.tid &&
+ lock->fnum == fsp->last_lock_failure.fnum &&
+ lock->start == fsp->last_lock_failure.start) {
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ if (!blocking_lock) {
+ fsp->last_lock_failure = *lock;
+ }
return NT_STATUS_LOCK_NOT_GRANTED;
}
@@ -316,8 +310,7 @@ static int lock_compare(const struct lock_struct *lck1,
****************************************************************************/
static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
- const struct lock_struct *plock,
- BOOL *my_lock_ctx)
+ const struct lock_struct *plock, BOOL blocking_lock)
{
unsigned int i;
files_struct *fsp = br_lck->fsp;
@@ -326,12 +319,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
for (i=0; i < br_lck->num_locks; i++) {
/* Do any Windows or POSIX locks conflict ? */
if (brl_conflict(&locks[i], plock)) {
- NTSTATUS status = brl_lock_failed(plock);;
- /* Did we block ourselves ? */
- if (brl_same_context(&locks[i].context, &plock->context)) {
- *my_lock_ctx = True;
- }
- return status;
+ return brl_lock_failed(fsp,plock,blocking_lock);
}
#if ZERO_ZERO
if (plock->start == 0 && plock->size == 0 &&
@@ -343,13 +331,19 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
/* We can get the Windows lock, now see if it needs to
be mapped into a lower level POSIX one, and if so can
- we get it ? We tell the lower lock layer about the
- lock type so it can cope with the difference between
- Windows "stacking" locks and POSIX "flat" ones. */
-
- if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
- if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, WINDOWS_LOCK)) {
- if (errno == EACCES || errno == EAGAIN) {
+ we get it ? */
+
+ if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(fsp->conn->params)) {
+ int errno_ret;
+ if (!set_posix_lock_windows_flavour(fsp,
+ plock->start,
+ plock->size,
+ plock->lock_type,
+ &plock->context,
+ locks,
+ br_lck->num_locks,
+ &errno_ret)) {
+ if (errno_ret == EACCES || errno_ret == EAGAIN) {
return NT_STATUS_FILE_LOCK_CONFLICT;
} else {
return map_nt_error_from_unix(errno);
@@ -375,9 +369,9 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
Cope with POSIX range splits and merges.
****************************************************************************/
-static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
- const struct lock_struct *ex,
- const struct lock_struct *plock,
+static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr, /* Output array. */
+ const struct lock_struct *ex, /* existing lock. */
+ const struct lock_struct *plock, /* proposed lock. */
BOOL *lock_was_added)
{
BOOL lock_types_differ = (ex->lock_type != plock->lock_type);
@@ -398,26 +392,26 @@ static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
+---------+
| ex |
+---------+
- +-------+
- | plock |
- +-------+
+ +-------+
+ | plock |
+ +-------+
OR....
+---------+
| ex |
+---------+
**********************************************/
- if ( (ex->start >= (plock->start + plock->size)) ||
- (plock->start >= (ex->start + ex->size))) {
+ if ( (ex->start > (plock->start + plock->size)) ||
+ (plock->start > (ex->start + ex->size))) {
/* No overlap with this lock - copy existing. */
memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
return 1;
}
/*********************************************
- +---------+
- | ex |
- +---------+
+ +---------------------------+
+ | ex |
+ +---------------------------+
+---------------------------+
| plock | -> replace with plock.
+---------------------------+
@@ -431,24 +425,32 @@ OR....
}
/*********************************************
- +---------------+
- | ex |
- +---------------+
+ +-----------------------+
+ | ex |
+ +-----------------------+
+ +---------------+
+ | plock |
+ +---------------+
+OR....
+ +-------+
+ | ex |
+ +-------+
+---------------+
| plock |
+---------------+
+
BECOMES....
+---------------+-------+
| plock | ex | - different lock types.
+---------------+-------+
-OR....
+OR.... (merge)
+-----------------------+
| ex | - same lock type.
+-----------------------+
**********************************************/
if ( (ex->start >= plock->start) &&
- (ex->start < plock->start + plock->size) &&
+ (ex->start <= plock->start + plock->size) &&
(ex->start + ex->size > plock->start + plock->size) ) {
*lock_was_added = True;
@@ -475,9 +477,16 @@ OR....
}
/*********************************************
- +---------------+
- | ex |
- +---------------+
+ +-----------------------+
+ | ex |
+ +-----------------------+
+ +---------------+
+ | plock |
+ +---------------+
+OR....
+ +-------+
+ | ex |
+ +-------+
+---------------+
| plock |
+---------------+
@@ -486,7 +495,7 @@ BECOMES....
| ex | plock | - different lock types
+-------+---------------+
-OR
+OR.... (merge)
+-----------------------+
| ex | - same lock type.
+-----------------------+
@@ -494,7 +503,7 @@ OR
**********************************************/
if ( (ex->start < plock->start) &&
- (ex->start + ex->size > plock->start) &&
+ (ex->start + ex->size >= plock->start) &&
(ex->start + ex->size <= plock->start + plock->size) ) {
*lock_was_added = True;
@@ -573,13 +582,13 @@ OR
****************************************************************************/
static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
- const struct lock_struct *plock,
- BOOL *my_lock_ctx)
+ const struct lock_struct *plock)
{
unsigned int i, count;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
struct lock_struct *tp;
BOOL lock_was_added = False;
+ BOOL signal_pending_read = False;
/* No zero-zero locks for POSIX. */
if (plock->start == 0 && plock->size == 0) {
@@ -603,23 +612,28 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
count = 0;
for (i=0; i < br_lck->num_locks; i++) {
- if (locks[i].lock_flav == WINDOWS_LOCK) {
+ struct lock_struct *curr_lock = &locks[i];
+
+ /* If we have a pending read lock, a lock downgrade should
+ trigger a lock re-evaluation. */
+ if (curr_lock->lock_type == PENDING_READ_LOCK &&
+ brl_pending_overlap(plock, curr_lock)) {
+ signal_pending_read = True;
+ }
+
+ if (curr_lock->lock_flav == WINDOWS_LOCK) {
/* Do any Windows flavour locks conflict ? */
- if (brl_conflict(&locks[i], plock)) {
- /* Did we block ourselves ? */
- if (brl_same_context(&locks[i].context, &plock->context)) {
- *my_lock_ctx = True;
- }
+ if (brl_conflict(curr_lock, plock)) {
/* No games with error messages. */
SAFE_FREE(tp);
return NT_STATUS_FILE_LOCK_CONFLICT;
}
/* Just copy the Windows lock into the new array. */
- memcpy(&tp[count], &locks[i], sizeof(struct lock_struct));
+ memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
count++;
} else {
/* POSIX conflict semantics are different. */
- if (brl_conflict_posix(&locks[i], plock)) {
+ if (brl_conflict_posix(curr_lock, plock)) {
/* Can't block ourselves with POSIX locks. */
/* No games with error messages. */
SAFE_FREE(tp);
@@ -627,24 +641,32 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
}
/* Work out overlaps. */
- count += brlock_posix_split_merge(&tp[count], &locks[i], plock, &lock_was_added);
+ count += brlock_posix_split_merge(&tp[count], curr_lock, plock, &lock_was_added);
}
}
+ if (!lock_was_added) {
+ memcpy(&tp[count], plock, sizeof(struct lock_struct));
+ count++;
+ }
+
/* We can get the POSIX lock, now see if it needs to
be mapped into a lower level POSIX one, and if so can
- we get it ? We well the lower lock layer about the
- lock type so it can cope with the difference between
- Windows "stacking" locks and POSIX "flat" ones. */
+ we get it ? */
-#if 0
- /* FIXME - this call doesn't work correctly yet for POSIX locks... */
+ if (!IS_PENDING_LOCK(plock->lock_type) && lp_posix_locking(br_lck->fsp->conn->params)) {
+ int errno_ret;
- if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
- files_struct *fsp = br_lck->fsp;
+ /* The lower layer just needs to attempt to
+ get the system POSIX lock. We've weeded out
+ any conflicts above. */
- if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) {
- if (errno == EACCES || errno == EAGAIN) {
+ if (!set_posix_lock_posix_flavour(br_lck->fsp,
+ plock->start,
+ plock->size,
+ plock->lock_type,
+ &errno_ret)) {
+ if (errno_ret == EACCES || errno_ret == EAGAIN) {
SAFE_FREE(tp);
return NT_STATUS_FILE_LOCK_CONFLICT;
} else {
@@ -653,12 +675,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
}
}
}
-#endif
-
- if (!lock_was_added) {
- memcpy(&tp[count], plock, sizeof(struct lock_struct));
- count++;
- }
/* Realloc so we don't leak entries per lock call. */
tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
@@ -668,7 +684,34 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
br_lck->num_locks = count;
SAFE_FREE(br_lck->lock_data);
br_lck->lock_data = (void *)tp;
+ locks = tp;
br_lck->modified = True;
+
+ /* A successful downgrade from write to read lock can trigger a lock
+ re-evalutation where waiting readers can now proceed. */
+
+ if (signal_pending_read) {
+ /* Send unlock messages to any pending read waiters that overlap. */
+ for (i=0; i < br_lck->num_locks; i++) {
+ struct lock_struct *pend_lock = &locks[i];
+
+ /* Ignore non-pending locks. */
+ if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
+ continue;
+ }
+
+ if (pend_lock->lock_type == PENDING_READ_LOCK &&
+ brl_pending_overlap(plock, pend_lock)) {
+ DEBUG(10,("brl_lock_posix: sending unlock message to pid %s\n",
+ procid_str_static(&pend_lock->context.pid )));
+
+ message_send_pid(pend_lock->context.pid,
+ MSG_SMB_UNLOCK,
+ NULL, 0, True);
+ }
+ }
+ }
+
return NT_STATUS_OK;
}
@@ -677,19 +720,17 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
****************************************************************************/
NTSTATUS brl_lock(struct byte_range_lock *br_lck,
- uint16 smbpid,
+ uint32 smbpid,
struct process_id pid,
br_off start,
br_off size,
enum brl_type lock_type,
enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ BOOL blocking_lock)
{
NTSTATUS ret;
struct lock_struct lock;
- *my_lock_ctx = False;
-
#if !ZERO_ZERO
if (start == 0 && size == 0) {
DEBUG(0,("client sent 0/0 lock - please report this\n"));
@@ -706,9 +747,9 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck,
lock.lock_flav = lock_flav;
if (lock_flav == WINDOWS_LOCK) {
- ret = brl_lock_windows(br_lck, &lock, my_lock_ctx);
+ ret = brl_lock_windows(br_lck, &lock, blocking_lock);
} else {
- ret = brl_lock_posix(br_lck, &lock, my_lock_ctx);
+ ret = brl_lock_posix(br_lck, &lock);
}
#if ZERO_ZERO
@@ -720,19 +761,6 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck,
}
/****************************************************************************
- Check if an unlock overlaps a pending lock.
-****************************************************************************/
-
-static BOOL brl_pending_overlap(const struct lock_struct *lock, const struct lock_struct *pend_lock)
-{
- if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start))
- return True;
- if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size))
- return True;
- return False;
-}
-
-/****************************************************************************
Unlock a range of bytes - Windows semantics.
****************************************************************************/
@@ -740,8 +768,12 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
{
unsigned int i, j;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
#if ZERO_ZERO
+ /* Delete write locks by preference... The lock list
+ is sorted in the zero zero case. */
+
for (i = 0; i < br_lck->num_locks; i++) {
struct lock_struct *lock = &locks[i];
@@ -753,16 +785,15 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
lock->size == plock->size) {
/* found it - delete it */
- if (i < br_lck->num_locks - 1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((br_lck->num_locks-1) - i));
- }
-
- br_lck->num_locks -= 1;
- br_lck->modified = True;
- return True;
+ deleted_lock_type = lock->lock_type;
+ break;
}
}
+
+ if (i != br_lck->num_locks) {
+ /* We found it - don't search again. */
+ goto unlock_continue;
+ }
#endif
for (i = 0; i < br_lck->num_locks; i++) {
@@ -774,6 +805,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
lock->lock_flav == WINDOWS_LOCK &&
lock->start == plock->start &&
lock->size == plock->size ) {
+ deleted_lock_type = lock->lock_type;
break;
}
}
@@ -783,9 +815,28 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
return False;
}
- /* Unlock any POSIX regions. */
- if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
- release_posix_lock(br_lck->fsp, plock->start, plock->size);
+#if ZERO_ZERO
+ unlock_continue:
+#endif
+
+ /* Actually delete the lock. */
+ if (i < br_lck->num_locks - 1) {
+ memmove(&locks[i], &locks[i+1],
+ sizeof(*locks)*((br_lck->num_locks-1) - i));
+ }
+
+ br_lck->num_locks -= 1;
+ br_lck->modified = True;
+
+ /* Unlock the underlying POSIX regions. */
+ if(lp_posix_locking(br_lck->fsp->conn->params)) {
+ release_posix_lock_windows_flavour(br_lck->fsp,
+ plock->start,
+ plock->size,
+ deleted_lock_type,
+ &plock->context,
+ locks,
+ br_lck->num_locks);
}
/* Send unlock messages to any pending waiters that overlap. */
@@ -793,7 +844,7 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
struct lock_struct *pend_lock = &locks[j];
/* Ignore non-pending locks. */
- if (pend_lock->lock_type != PENDING_LOCK) {
+ if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
continue;
}
@@ -802,22 +853,12 @@ static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock
DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
procid_str_static(&pend_lock->context.pid )));
- become_root();
message_send_pid(pend_lock->context.pid,
MSG_SMB_UNLOCK,
NULL, 0, True);
- unbecome_root();
}
}
- /* Actually delete the lock. */
- if (i < br_lck->num_locks - 1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((br_lck->num_locks-1) - i));
- }
-
- br_lck->num_locks -= 1;
- br_lck->modified = True;
return True;
}
@@ -861,9 +902,8 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
BOOL lock_was_added = False;
unsigned int tmp_count;
-
/* Only remove our own locks - ignore fnum. */
- if (lock->lock_type == PENDING_LOCK ||
+ if (IS_PENDING_LOCK(lock->lock_type) ||
!brl_same_context(&lock->context, &plock->context)) {
memcpy(&tp[count], lock, sizeof(struct lock_struct));
count++;
@@ -894,13 +934,18 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK);
memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
+ if (tmp_lock[0].size != locks[i].size) {
+ overlap_found = True;
+ }
} else {
SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK);
SMB_ASSERT(tmp_lock[1].lock_type == locks[i].lock_type);
memcpy(&tp[count], &tmp_lock[1], sizeof(struct lock_struct));
+ if (tmp_lock[1].start != locks[i].start) {
+ overlap_found = True;
+ }
}
count++;
- overlap_found = True;
continue;
} else {
/* tmp_count == 3 - (we split a lock range in two). */
@@ -932,14 +977,15 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
return True;
}
-#if 0
- /* FIXME - this call doesn't work correctly yet for POSIX locks... */
-
/* Unlock any POSIX regions. */
- if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
- release_posix_lock(br_lck->fsp, plock->start, plock->size);
+ if(lp_posix_locking(br_lck->fsp->conn->params)) {
+ release_posix_lock_posix_flavour(br_lck->fsp,
+ plock->start,
+ plock->size,
+ &plock->context,
+ tp,
+ count);
}
-#endif
/* Realloc so we don't leak entries per unlock call. */
if (count) {
@@ -956,7 +1002,8 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
br_lck->num_locks = count;
SAFE_FREE(br_lck->lock_data);
- locks = br_lck->lock_data = (void *)tp;
+ locks = tp;
+ br_lck->lock_data = (void *)tp;
br_lck->modified = True;
/* Send unlock messages to any pending waiters that overlap. */
@@ -965,7 +1012,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
struct lock_struct *pend_lock = &locks[j];
/* Ignore non-pending locks. */
- if (pend_lock->lock_type != PENDING_LOCK) {
+ if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
continue;
}
@@ -974,11 +1021,9 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
procid_str_static(&pend_lock->context.pid )));
- become_root();
message_send_pid(pend_lock->context.pid,
MSG_SMB_UNLOCK,
NULL, 0, True);
- unbecome_root();
}
}
@@ -990,7 +1035,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
****************************************************************************/
BOOL brl_unlock(struct byte_range_lock *br_lck,
- uint16 smbpid,
+ uint32 smbpid,
struct process_id pid,
br_off start,
br_off size,
@@ -1020,7 +1065,7 @@ BOOL brl_unlock(struct byte_range_lock *br_lck,
****************************************************************************/
BOOL brl_locktest(struct byte_range_lock *br_lck,
- uint16 smbpid,
+ uint32 smbpid,
struct process_id pid,
br_off start,
br_off size,
@@ -1030,7 +1075,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck,
BOOL ret = True;
unsigned int i;
struct lock_struct lock;
- struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
files_struct *fsp = br_lck->fsp;
lock.context.smbpid = smbpid;
@@ -1058,7 +1103,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck,
* This only conflicts with Windows locks, not POSIX locks.
*/
- if(lp_posix_locking(fsp->conn->cnum) && (lock_flav == WINDOWS_LOCK)) {
+ if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) {
ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
@@ -1078,7 +1123,7 @@ BOOL brl_locktest(struct byte_range_lock *br_lck,
****************************************************************************/
NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
- uint16 *psmbpid,
+ uint32 *psmbpid,
struct process_id pid,
br_off *pstart,
br_off *psize,
@@ -1087,7 +1132,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
{
unsigned int i;
struct lock_struct lock;
- struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ const struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
files_struct *fsp = br_lck->fsp;
lock.context.smbpid = *psmbpid;
@@ -1101,7 +1146,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
/* Make sure existing locks don't conflict */
for (i=0; i < br_lck->num_locks; i++) {
- struct lock_struct *exlock = &locks[i];
+ const struct lock_struct *exlock = &locks[i];
BOOL conflict = False;
if (exlock->lock_flav == WINDOWS_LOCK) {
@@ -1124,7 +1169,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
* see if there is a POSIX lock from a UNIX or NFS process.
*/
- if(lp_posix_locking(fsp->conn->cnum)) {
+ if(lp_posix_locking(fsp->conn->params)) {
BOOL ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n",
@@ -1141,13 +1186,12 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
return NT_STATUS_OK;
}
-
/****************************************************************************
Remove a particular pending lock.
****************************************************************************/
-BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
- uint16 smbpid,
+BOOL brl_lock_cancel(struct byte_range_lock *br_lck,
+ uint32 smbpid,
struct process_id pid,
br_off start,
br_off size,
@@ -1167,7 +1211,7 @@ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
/* For pending locks we *always* care about the fnum. */
if (brl_same_context(&lock->context, &context) &&
lock->fnum == br_lck->fsp->fnum &&
- lock->lock_type == PENDING_LOCK &&
+ IS_PENDING_LOCK(lock->lock_type) &&
lock->lock_flav == lock_flav &&
lock->start == start &&
lock->size == size) {
@@ -1191,18 +1235,75 @@ BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
return True;
}
-
/****************************************************************************
Remove any locks associated with a open file.
+ We return True if this process owns any other Windows locks on this
+ fd and so we should not immediately close the fd.
****************************************************************************/
-void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
+void brl_close_fnum(struct byte_range_lock *br_lck)
{
files_struct *fsp = br_lck->fsp;
uint16 tid = fsp->conn->cnum;
int fnum = fsp->fnum;
unsigned int i, j, dcount=0;
+ int num_deleted_windows_locks = 0;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ struct process_id pid = procid_self();
+ BOOL unlock_individually = False;
+
+ if(lp_posix_locking(fsp->conn->params)) {
+
+ /* Check if there are any Windows locks associated with this dev/ino
+ pair that are not this fnum. If so we need to call unlock on each
+ one in order to release the system POSIX locks correctly. */
+
+ for (i=0; i < br_lck->num_locks; i++) {
+ struct lock_struct *lock = &locks[i];
+
+ if (!procid_equal(&lock->context.pid, &pid)) {
+ continue;
+ }
+
+ if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
+ continue; /* Ignore pending. */
+ }
+
+ if (lock->context.tid != tid || lock->fnum != fnum) {
+ unlock_individually = True;
+ break;
+ }
+ }
+
+ if (unlock_individually) {
+ struct lock_struct *locks_copy;
+ unsigned int num_locks_copy;
+
+ /* Copy the current lock array. */
+ locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
+ if (!locks_copy) {
+ smb_panic("brl_close_fnum: talloc fail.\n");
+ }
+ num_locks_copy = br_lck->num_locks;
+
+ for (i=0; i < num_locks_copy; i++) {
+ struct lock_struct *lock = &locks_copy[i];
+
+ if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) &&
+ (lock->fnum == fnum)) {
+ brl_unlock(br_lck,
+ lock->context.smbpid,
+ pid,
+ lock->start,
+ lock->size,
+ lock->lock_flav);
+ }
+ }
+ return;
+ }
+ }
+
+ /* We can bulk delete - any POSIX locks will be removed when the fd closes. */
/* Remove any existing locks for this fnum (or any fnum if they're POSIX). */
@@ -1213,6 +1314,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) {
if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) {
del_this_lock = True;
+ num_deleted_windows_locks++;
} else if (lock->lock_flav == POSIX_LOCK) {
del_this_lock = True;
}
@@ -1224,7 +1326,7 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
struct lock_struct *pend_lock = &locks[j];
/* Ignore our own or non-pending locks. */
- if (pend_lock->lock_type != PENDING_LOCK) {
+ if (!IS_PENDING_LOCK(pend_lock->lock_type)) {
continue;
}
@@ -1238,11 +1340,9 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
/* We could send specific lock info here... */
if (brl_pending_overlap(lock, pend_lock)) {
- become_root();
message_send_pid(pend_lock->context.pid,
MSG_SMB_UNLOCK,
NULL, 0, True);
- unbecome_root();
}
}
@@ -1257,6 +1357,11 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
dcount++;
}
}
+
+ if(lp_posix_locking(fsp->conn->params) && num_deleted_windows_locks) {
+ /* Reduce the Windows lock POSIX reference count on this dev/ino pair. */
+ reduce_windows_lock_ref_count(fsp, num_deleted_windows_locks);
+ }
}
/****************************************************************************
@@ -1345,7 +1450,7 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
}
if (orig_num_locks != num_locks) {
- dbuf.dptr = (void *)locks;
+ dbuf.dptr = (char *)locks;
dbuf.dsize = num_locks * sizeof(*locks);
if (dbuf.dsize) {
@@ -1387,13 +1492,17 @@ int brl_forall(BRLOCK_FN(fn))
Unlock the record.
********************************************************************/
-int byte_range_lock_destructor(struct byte_range_lock *br_lck)
+static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
{
TDB_DATA key;
key.dptr = (char *)&br_lck->key;
key.dsize = sizeof(struct lock_key);
+ if (br_lck->read_only) {
+ SMB_ASSERT(!br_lck->modified);
+ }
+
if (!br_lck->modified) {
goto done;
}
@@ -1405,7 +1514,7 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck)
}
} else {
TDB_DATA data;
- data.dptr = br_lck->lock_data;
+ data.dptr = (char *)br_lck->lock_data;
data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
@@ -1415,22 +1524,25 @@ int byte_range_lock_destructor(struct byte_range_lock *br_lck)
done:
- tdb_chainunlock(tdb, key);
+ if (!br_lck->read_only) {
+ tdb_chainunlock(tdb, key);
+ }
SAFE_FREE(br_lck->lock_data);
- SAFE_FREE(br_lck);
return 0;
}
/*******************************************************************
Fetch a set of byte range lock data from the database.
Leave the record locked.
+ TALLOC_FREE(brl) will release the lock in the destructor.
********************************************************************/
-struct byte_range_lock *brl_get_locks(files_struct *fsp)
+static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx,
+ files_struct *fsp, BOOL read_only)
{
TDB_DATA key;
TDB_DATA data;
- struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock);
+ struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock);
if (br_lck == NULL) {
return NULL;
@@ -1446,12 +1558,25 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
key.dptr = (char *)&br_lck->key;
key.dsize = sizeof(struct lock_key);
- if (tdb_chainlock(tdb, key) != 0) {
- DEBUG(3, ("Could not lock byte range lock entry\n"));
- SAFE_FREE(br_lck);
- return NULL;
+ if (!fsp->lockdb_clean) {
+ /* We must be read/write to clean
+ the dead entries. */
+ read_only = False;
}
+ if (read_only) {
+ br_lck->read_only = True;
+ } else {
+ if (tdb_chainlock(tdb, key) != 0) {
+ DEBUG(3, ("Could not lock byte range lock entry\n"));
+ TALLOC_FREE(br_lck);
+ return NULL;
+ }
+ br_lck->read_only = False;
+ }
+
+ talloc_set_destructor(br_lck, byte_range_lock_destructor);
+
data = tdb_fetch(tdb, key);
br_lck->lock_data = (void *)data.dptr;
br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
@@ -1462,13 +1587,22 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
/* Go through and ensure all entries exist - remove any that don't. */
/* Makes the lockdb self cleaning at low cost. */
- if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) {
- tdb_chainunlock(tdb, key);
+ struct lock_struct *locks =
+ (struct lock_struct *)br_lck->lock_data;
+
+ if (!validate_lock_entries(&br_lck->num_locks, &locks)) {
SAFE_FREE(br_lck->lock_data);
- SAFE_FREE(br_lck);
+ TALLOC_FREE(br_lck);
return NULL;
}
+ /*
+ * validate_lock_entries might have changed locks. We can't
+ * use a direct pointer here because otherwise gcc warnes
+ * about strict aliasing rules being violated.
+ */
+ br_lck->lock_data = locks;
+
/* Mark the lockdb as "clean" as seen from this open file. */
fsp->lockdb_clean = True;
}
@@ -1476,7 +1610,7 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
if (DEBUGLEVEL >= 10) {
unsigned int i;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
- DEBUG(10,("brl_get_locks: %u current locks on dev=%.0f, inode=%.0f\n",
+ DEBUG(10,("brl_get_locks_internal: %u current locks on dev=%.0f, inode=%.0f\n",
br_lck->num_locks,
(double)fsp->dev, (double)fsp->inode ));
for( i = 0; i < br_lck->num_locks; i++) {
@@ -1485,3 +1619,15 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
}
return br_lck;
}
+
+struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx,
+ files_struct *fsp)
+{
+ return brl_get_locks_internal(mem_ctx, fsp, False);
+}
+
+struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx,
+ files_struct *fsp)
+{
+ return brl_get_locks_internal(mem_ctx, fsp, True);
+}
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 9d3ca956014..ffac43aff59 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -37,7 +37,6 @@
*/
#include "includes.h"
-uint16 global_smbpid;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_LOCKING
@@ -56,8 +55,10 @@ const char *lock_type_name(enum brl_type lock_type)
return "READ";
case WRITE_LOCK:
return "WRITE";
- case PENDING_LOCK:
- return "PENDING";
+ case PENDING_READ_LOCK:
+ return "PENDING_READ";
+ case PENDING_WRITE_LOCK:
+ return "PENDING_WRITE";
default:
return "other";
}
@@ -74,20 +75,20 @@ const char *lock_flav_name(enum brl_flavour lock_flav)
****************************************************************************/
BOOL is_locked(files_struct *fsp,
+ uint32 smbpid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
enum brl_type lock_type)
{
- int snum = SNUM(fsp->conn);
- int strict_locking = lp_strict_locking(snum);
- enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
+ int strict_locking = lp_strict_locking(fsp->conn->params);
+ enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp);
BOOL ret = True;
if (count == 0) {
return False;
}
- if (!lp_locking(snum) || !strict_locking) {
+ if (!lp_locking(fsp->conn->params) || !strict_locking) {
return False;
}
@@ -100,32 +101,32 @@ BOOL is_locked(files_struct *fsp,
DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
ret = False;
} else {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp);
if (!br_lck) {
return False;
}
ret = !brl_locktest(br_lck,
- global_smbpid,
+ smbpid,
procid_self(),
offset,
count,
lock_type,
lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
} else {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks_readonly(NULL, fsp);
if (!br_lck) {
return False;
}
ret = !brl_locktest(br_lck,
- global_smbpid,
+ smbpid,
procid_self(),
offset,
count,
lock_type,
lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
@@ -141,7 +142,7 @@ BOOL is_locked(files_struct *fsp,
****************************************************************************/
NTSTATUS query_lock(files_struct *fsp,
- uint16 *psmbpid,
+ uint32 *psmbpid,
SMB_BIG_UINT *pcount,
SMB_BIG_UINT *poffset,
enum brl_type *plock_type,
@@ -150,15 +151,15 @@ NTSTATUS query_lock(files_struct *fsp,
struct byte_range_lock *br_lck = NULL;
NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
- if (!OPEN_FSP(fsp) || !fsp->can_lock) {
- return NT_STATUS_INVALID_HANDLE;
+ if (!fsp->can_lock) {
+ return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
}
- if (!lp_locking(SNUM(fsp->conn))) {
+ if (!lp_locking(fsp->conn->params)) {
return NT_STATUS_OK;
}
- br_lck = brl_get_locks(fsp);
+ br_lck = brl_get_locks_readonly(NULL, fsp);
if (!br_lck) {
return NT_STATUS_NO_MEMORY;
}
@@ -171,7 +172,7 @@ NTSTATUS query_lock(files_struct *fsp,
plock_type,
lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
return status;
}
@@ -179,23 +180,25 @@ NTSTATUS query_lock(files_struct *fsp,
Utility function called by locking requests.
****************************************************************************/
-NTSTATUS do_lock(files_struct *fsp,
- uint16 lock_pid,
+struct byte_range_lock *do_lock(files_struct *fsp,
+ uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
enum brl_type lock_type,
enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ BOOL blocking_lock,
+ NTSTATUS *perr)
{
struct byte_range_lock *br_lck = NULL;
- NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
- if (!OPEN_FSP(fsp) || !fsp->can_lock) {
- return NT_STATUS_INVALID_HANDLE;
+ if (!fsp->can_lock) {
+ *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
+ return NULL;
}
- if (!lp_locking(SNUM(fsp->conn))) {
- return NT_STATUS_OK;
+ if (!lp_locking(fsp->conn->params)) {
+ *perr = NT_STATUS_OK;
+ return NULL;
}
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
@@ -204,89 +207,76 @@ NTSTATUS do_lock(files_struct *fsp,
lock_flav_name(lock_flav), lock_type_name(lock_type),
(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
- br_lck = brl_get_locks(fsp);
+ br_lck = brl_get_locks(NULL, fsp);
if (!br_lck) {
- return NT_STATUS_NO_MEMORY;
+ *perr = NT_STATUS_NO_MEMORY;
+ return NULL;
}
- status = brl_lock(br_lck,
+ *perr = brl_lock(br_lck,
lock_pid,
procid_self(),
offset,
count,
lock_type,
lock_flav,
- my_lock_ctx);
+ blocking_lock);
- byte_range_lock_destructor(br_lck);
- return status;
+ return br_lck;
}
/****************************************************************************
- Utility function called by locking requests. This is *DISGUSTING*. It also
- appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
- is so slow on the locking tests...... ? This is the reason. Much though I hate
- it, we need this. JRA.
+ Utility function called by unlocking requests.
****************************************************************************/
-NTSTATUS do_lock_spin(files_struct *fsp,
- uint16 lock_pid,
+NTSTATUS do_unlock(files_struct *fsp,
+ uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
- enum brl_type lock_type,
- enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ enum brl_flavour lock_flav)
{
- int j, maxj = lp_lock_spin_count();
- int sleeptime = lp_lock_sleep_time();
- NTSTATUS status, ret;
-
- if (maxj <= 0) {
- maxj = 1;
+ BOOL ok = False;
+ struct byte_range_lock *br_lck = NULL;
+
+ if (!fsp->can_lock) {
+ return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
}
+
+ if (!lp_locking(fsp->conn->params)) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
+ (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
- ret = NT_STATUS_OK; /* to keep dumb compilers happy */
-
- for (j = 0; j < maxj; j++) {
- status = do_lock(fsp,
- lock_pid,
- count,
- offset,
- lock_type,
- lock_flav,
- my_lock_ctx);
-
- if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
- return status;
- }
- /* if we do fail then return the first error code we got */
- if (j == 0) {
- ret = status;
- /* Don't spin if we blocked ourselves. */
- if (*my_lock_ctx) {
- return ret;
- }
+ br_lck = brl_get_locks(NULL, fsp);
+ if (!br_lck) {
+ return NT_STATUS_NO_MEMORY;
+ }
- /* Only spin for Windows locks. */
- if (lock_flav == POSIX_LOCK) {
- return ret;
- }
- }
+ ok = brl_unlock(br_lck,
+ lock_pid,
+ procid_self(),
+ offset,
+ count,
+ lock_flav);
+
+ TALLOC_FREE(br_lck);
- if (sleeptime) {
- sys_usleep(sleeptime);
- }
+ if (!ok) {
+ DEBUG(10,("do_unlock: returning ERRlock.\n" ));
+ return NT_STATUS_RANGE_NOT_LOCKED;
}
- return ret;
+
+ return NT_STATUS_OK;
}
/****************************************************************************
- Utility function called by unlocking requests.
+ Cancel any pending blocked locks.
****************************************************************************/
-NTSTATUS do_unlock(files_struct *fsp,
- uint16 lock_pid,
+NTSTATUS do_lock_cancel(files_struct *fsp,
+ uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
enum brl_flavour lock_flav)
@@ -294,34 +284,35 @@ NTSTATUS do_unlock(files_struct *fsp,
BOOL ok = False;
struct byte_range_lock *br_lck = NULL;
- if (!lp_locking(SNUM(fsp->conn))) {
- return NT_STATUS_OK;
+ if (!fsp->can_lock) {
+ return fsp->is_directory ?
+ NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
}
- if (!OPEN_FSP(fsp) || !fsp->can_lock) {
- return NT_STATUS_INVALID_HANDLE;
+ if (!lp_locking(fsp->conn->params)) {
+ return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
-
- DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
+
+ DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
- br_lck = brl_get_locks(fsp);
+ br_lck = brl_get_locks(NULL, fsp);
if (!br_lck) {
return NT_STATUS_NO_MEMORY;
}
- ok = brl_unlock(br_lck,
+ ok = brl_lock_cancel(br_lck,
lock_pid,
procid_self(),
offset,
count,
lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
if (!ok) {
- DEBUG(10,("do_unlock: returning ERRlock.\n" ));
- return NT_STATUS_RANGE_NOT_LOCKED;
+ DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
+ return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
return NT_STATUS_OK;
@@ -334,25 +325,17 @@ NTSTATUS do_unlock(files_struct *fsp,
void locking_close_file(files_struct *fsp)
{
struct byte_range_lock *br_lck;
- struct process_id pid = procid_self();
- if (!lp_locking(SNUM(fsp->conn)))
+ if (!lp_locking(fsp->conn->params)) {
return;
-
- /*
- * Just release all the brl locks, no need to release individually.
- */
-
- br_lck = brl_get_locks(fsp);
- if (br_lck) {
- brl_close_fnum(br_lck, pid);
- byte_range_lock_destructor(br_lck);
}
- if(lp_posix_locking(SNUM(fsp->conn))) {
- /* Release all the POSIX locks.*/
- posix_locking_close_file(fsp);
+ br_lck = brl_get_locks(NULL,fsp);
+ if (br_lck) {
+ cancel_pending_lock_requests_by_fid(fsp, br_lck);
+ brl_close_fnum(br_lck);
+ TALLOC_FREE(br_lck);
}
}
@@ -443,13 +426,14 @@ char *share_mode_str(int num, struct share_mode_entry *e)
slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s "
"pid = %s, share_access = 0x%x, private_options = 0x%x, "
"access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, "
- "uid = %u, dev = 0x%x, inode = %.0f",
+ "uid = %u, flags = %u, dev = 0x%x, inode = %.0f",
num,
e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
procid_str_static(&e->pid),
e->share_access, e->private_options,
e->access_mask, e->op_mid, e->op_type, e->share_file_id,
- (unsigned int)e->uid, (unsigned int)e->dev, (double)e->inode );
+ (unsigned int)e->uid, (unsigned int)e->flags,
+ (unsigned int)e->dev, (double)e->inode );
return share_str;
}
@@ -490,14 +474,11 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
data = (struct locking_data *)dbuf.dptr;
lck->delete_on_close = data->u.s.delete_on_close;
- lck->initial_delete_on_close = data->u.s.initial_delete_on_close;
lck->num_share_modes = data->u.s.num_share_mode_entries;
DEBUG(10, ("parse_share_modes: delete_on_close: %d, "
- "initial_delete_on_close: %d, "
"num_share_modes: %d\n",
lck->delete_on_close,
- lck->initial_delete_on_close,
lck->num_share_modes));
if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
@@ -516,9 +497,10 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
- lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data),
- lck->num_share_modes *
- sizeof(struct share_mode_entry));
+ lck->share_modes = (struct share_mode_entry *)
+ talloc_memdup(lck, dbuf.dptr+sizeof(*data),
+ lck->num_share_modes *
+ sizeof(struct share_mode_entry));
if (lck->share_modes == NULL) {
smb_panic("talloc failed\n");
@@ -577,12 +559,18 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
(lck->num_share_modes *
sizeof(struct share_mode_entry)) +
data->u.s.delete_token_size );
+ if (lck->servicepath == NULL) {
+ smb_panic("talloc_strdup failed\n");
+ }
lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry)) +
data->u.s.delete_token_size +
strlen(lck->servicepath) + 1 );
+ if (lck->filename == NULL) {
+ smb_panic("talloc_strdup failed\n");
+ }
/*
* Ensure that each entry has a real process attached.
@@ -635,7 +623,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
delete_token_size +
sp_len + 1 +
strlen(lck->filename) + 1;
- result.dptr = talloc_size(lck, result.dsize);
+ result.dptr = TALLOC_ARRAY(lck, char, result.dsize);
if (result.dptr == NULL) {
smb_panic("talloc failed\n");
@@ -645,11 +633,9 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
ZERO_STRUCTP(data);
data->u.s.num_share_mode_entries = lck->num_share_modes;
data->u.s.delete_on_close = lck->delete_on_close;
- data->u.s.initial_delete_on_close = lck->initial_delete_on_close;
data->u.s.delete_token_size = delete_token_size;
- DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n",
+ DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n",
data->u.s.delete_on_close,
- data->u.s.initial_delete_on_close,
(unsigned int)data->u.s.delete_token_size,
data->u.s.num_share_mode_entries));
memcpy(result.dptr + sizeof(*data), lck->share_modes,
@@ -687,10 +673,8 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
return result;
}
-static int share_mode_lock_destructor(void *p)
+static int share_mode_lock_destructor(struct share_mode_lock *lck)
{
- struct share_mode_lock *lck =
- talloc_get_type_abort(p, struct share_mode_lock);
TDB_DATA key = locking_key(lck->dev, lck->ino);
TDB_DATA data;
@@ -746,7 +730,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
lck->share_modes = NULL;
lck->delete_token = NULL;
lck->delete_on_close = False;
- lck->initial_delete_on_close = False;
lck->fresh = False;
lck->modified = False;
@@ -838,7 +821,7 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1;
/* Set up the name changed message. */
- frm = TALLOC(lck, msg_len);
+ frm = TALLOC_ARRAY(lck, char, msg_len);
if (!frm) {
return False;
}
@@ -862,16 +845,14 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
continue;
}
- DEBUG(10,("rename_share_filename: sending rename message to pid %u "
+ DEBUG(10,("rename_share_filename: sending rename message to pid %s "
"dev %x, inode %.0f sharepath %s newname %s\n",
- (unsigned int)procid_to_pid(&se->pid),
+ procid_str_static(&se->pid),
(unsigned int)lck->dev, (double)lck->ino,
lck->servicepath, lck->filename ));
- become_root();
message_send_pid(se->pid, MSG_SMB_FILE_RENAME,
frm, msg_len, True);
- unbecome_root();
}
return True;
@@ -932,6 +913,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
e->inode = fsp->inode;
e->share_file_id = fsp->fh->file_id;
e->uid = (uint32)uid;
+ e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
}
static void fill_deferred_open_entry(struct share_mode_entry *e,
@@ -947,6 +929,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e,
e->dev = dev;
e->inode = ino;
e->uid = (uint32)-1;
+ e->flags = 0;
}
static void add_share_mode_entry(struct share_mode_lock *lck,
@@ -1166,6 +1149,11 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
return NT_STATUS_ACCESS_DENIED;
}
+ /* Don't allow delete on close for non-empty directories. */
+ if (fsp->is_directory) {
+ return can_delete_directory(fsp->conn, fsp->fsp_name);
+ }
+
return NT_STATUS_OK;
}
@@ -1225,11 +1213,22 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok
changed the delete on close flag. This will be noticed
in the close code, the last closer will delete the file
if flag is set.
- Note that setting this to any value clears the initial_delete_on_close flag.
- If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the
- lck entry.
+ This makes a copy of any UNIX_USER_TOKEN into the
+ lck entry. This function is used when the lock is already granted.
****************************************************************************/
+void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
+{
+ if (lck->delete_on_close != delete_on_close) {
+ set_delete_on_close_token(lck, tok);
+ lck->delete_on_close = delete_on_close;
+ if (delete_on_close) {
+ SMB_ASSERT(lck->delete_token != NULL);
+ }
+ lck->modified = True;
+ }
+}
+
BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
{
struct share_mode_lock *lck;
@@ -1248,33 +1247,33 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE
return False;
}
- if (lck->delete_on_close != delete_on_close) {
- set_delete_on_close_token(lck, tok);
- lck->delete_on_close = delete_on_close;
- if (delete_on_close) {
- SMB_ASSERT(lck->delete_token != NULL);
- }
- lck->modified = True;
- }
+ set_delete_on_close_lck(lck, delete_on_close, tok);
- if (lck->initial_delete_on_close) {
- lck->initial_delete_on_close = False;
- lck->modified = True;
+ if (fsp->is_directory) {
+ send_stat_cache_delete_message(fsp->fsp_name);
}
TALLOC_FREE(lck);
return True;
}
+struct forall_state {
+ void (*fn)(const struct share_mode_entry *entry,
+ const char *sharepath,
+ const char *fname,
+ void *private_data);
+ void *private_data;
+};
+
static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
- void *state)
+ void *_state)
{
+ struct forall_state *state = (struct forall_state *)_state;
struct locking_data *data;
struct share_mode_entry *shares;
const char *sharepath;
const char *fname;
int i;
- LOCKING_FN(traverse_callback) = (LOCKING_FN_CAST())state;
/* Ensure this is a locking_key record. */
if (kbuf.dsize != sizeof(struct locking_key))
@@ -1291,7 +1290,8 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
strlen(sharepath) + 1;
for (i=0;i<data->u.s.num_share_mode_entries;i++) {
- traverse_callback(&shares[i], sharepath, fname);
+ state->fn(&shares[i], sharepath, fname,
+ state->private_data);
}
return 0;
}
@@ -1301,9 +1301,17 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
share mode system.
********************************************************************/
-int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, const char *))
+int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
+ const char *, void *),
+ void *private_data)
{
+ struct forall_state state;
+
if (tdb == NULL)
return 0;
- return tdb_traverse(tdb, traverse_fn, fn);
+
+ state.fn = fn;
+ state.private_data = private_data;
+
+ return tdb_traverse(tdb, traverse_fn, (void *)&state);
}
diff --git a/source/locking/posix.c b/source/locking/posix.c
index 4a5f59b622d..62804eb8e34 100644
--- a/source/locking/posix.c
+++ b/source/locking/posix.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
Locking functions
- Copyright (C) Jeremy Allison 1992-2000
+ Copyright (C) Jeremy Allison 1992-2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,481 +28,17 @@
#define DBGC_CLASS DBGC_LOCKING
/*
- * The POSIX locking database handle.
- */
-
-static TDB_CONTEXT *posix_lock_tdb;
-
-/*
* The pending close database handle.
*/
static TDB_CONTEXT *posix_pending_close_tdb;
-/*
- * The data in POSIX lock records is an unsorted linear array of these
- * records. It is unnecessary to store the count as tdb provides the
- * size of the record.
- */
-
-struct posix_lock {
- int fd;
- SMB_OFF_T start;
- SMB_OFF_T size;
- int lock_type;
-};
-
-/*
- * The data in POSIX pending close records is an unsorted linear array of int
- * records. It is unnecessary to store the count as tdb provides the
- * size of the record.
- */
-
-/* The key used in both the POSIX databases. */
-
-struct posix_lock_key {
- SMB_DEV_T device;
- SMB_INO_T inode;
-};
-
-/*******************************************************************
- Form a static locking key for a dev/inode pair.
-******************************************************************/
-
-static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
-{
- static struct posix_lock_key key;
- TDB_DATA kbuf;
-
- memset(&key, '\0', sizeof(key));
- key.device = dev;
- key.inode = inode;
- kbuf.dptr = (char *)&key;
- kbuf.dsize = sizeof(key);
- return kbuf;
-}
-
-/*******************************************************************
- Convenience function to get a key from an fsp.
-******************************************************************/
-
-static TDB_DATA locking_key_fsp(files_struct *fsp)
-{
- return locking_key(fsp->dev, fsp->inode);
-}
-
-/****************************************************************************
- Add an fd to the pending close tdb.
-****************************************************************************/
-
-static BOOL add_fd_to_close_entry(files_struct *fsp)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
-
- dbuf.dptr = NULL;
- dbuf.dsize = 0;
-
- dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
- dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
- if (!dbuf.dptr) {
- DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
- return False;
- }
-
- memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
- dbuf.dsize += sizeof(int);
-
- if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
- DEBUG(0,("add_fd_to_close_entry: tdb_store fail !\n"));
- }
-
- SAFE_FREE(dbuf.dptr);
- return True;
-}
-
-/****************************************************************************
- Remove all fd entries for a specific dev/inode pair from the tdb.
-****************************************************************************/
-
-static void delete_close_entries(files_struct *fsp)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
-
- if (tdb_delete(posix_pending_close_tdb, kbuf) == -1)
- DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
-
-/****************************************************************************
- Get the array of POSIX pending close records for an open fsp. Caller must
- free. Returns number of entries.
-****************************************************************************/
-
-static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- size_t count = 0;
-
- *entries = NULL;
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
-
- if (!dbuf.dptr) {
- return 0;
- }
-
- *entries = (int *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(int));
-
- return count;
-}
-
/****************************************************************************
- Get the array of POSIX locks for an fsp. Caller must free. Returns
- number of entries.
+ First - the functions that deal with the underlying system locks - these
+ functions are used no matter if we're mapping CIFS Windows locks or CIFS
+ POSIX locks onto POSIX.
****************************************************************************/
-static size_t get_posix_lock_entries(files_struct *fsp, struct posix_lock **entries)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- size_t count = 0;
-
- *entries = NULL;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr) {
- return 0;
- }
-
- *entries = (struct posix_lock *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
- return count;
-}
-
-/****************************************************************************
- Deal with pending closes needed by POSIX locking support.
- Note that posix_locking_close_file() is expected to have been called
- to delete all locks on this fsp before this function is called.
-****************************************************************************/
-
-int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
-{
- int saved_errno = 0;
- int ret;
- size_t count, i;
- struct posix_lock *entries = NULL;
- int *fd_array = NULL;
- BOOL locks_on_other_fds = False;
-
- if (!lp_posix_locking(SNUM(conn))) {
- /*
- * No POSIX to worry about, just close.
- */
- ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
- fsp->fh->fd = -1;
- return ret;
- }
-
- /*
- * Get the number of outstanding POSIX locks on this dev/inode pair.
- */
-
- count = get_posix_lock_entries(fsp, &entries);
-
- /*
- * Check if there are any outstanding locks belonging to
- * other fd's. This should never be the case if posix_locking_close_file()
- * has been called first, but it never hurts to be *sure*.
- */
-
- for (i = 0; i < count; i++) {
- if (entries[i].fd != fsp->fh->fd) {
- locks_on_other_fds = True;
- break;
- }
- }
-
- if (locks_on_other_fds) {
-
- /*
- * There are outstanding locks on this dev/inode pair on other fds.
- * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
- */
-
- if (!add_fd_to_close_entry(fsp)) {
- SAFE_FREE(entries);
- return -1;
- }
-
- SAFE_FREE(entries);
- fsp->fh->fd = -1;
- return 0;
- }
-
- SAFE_FREE(entries);
-
- /*
- * No outstanding POSIX locks. Get the pending close fd's
- * from the tdb and close them all.
- */
-
- count = get_posix_pending_close_entries(fsp, &fd_array);
-
- if (count) {
- DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
-
- for(i = 0; i < count; i++) {
- if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
- saved_errno = errno;
- }
- }
-
- /*
- * Delete all fd's stored in the tdb
- * for this dev/inode pair.
- */
-
- delete_close_entries(fsp);
- }
-
- SAFE_FREE(fd_array);
-
- /*
- * Finally close the fd associated with this fsp.
- */
-
- ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
-
- if (saved_errno != 0) {
- errno = saved_errno;
- ret = -1;
- }
-
- fsp->fh->fd = -1;
-
- return ret;
-}
-
-/****************************************************************************
- Debugging aid :-).
-****************************************************************************/
-
-static const char *posix_lock_type_name(int lock_type)
-{
- return (lock_type == F_RDLCK) ? "READ" : "WRITE";
-}
-
-/****************************************************************************
- Delete a POSIX lock entry by index number. Used if the tdb add succeeds, but
- then the POSIX fcntl lock fails.
-****************************************************************************/
-
-static BOOL delete_posix_lock_entry_by_index(files_struct *fsp, size_t entry)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock *locks;
- size_t count;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr) {
- DEBUG(10,("delete_posix_lock_entry_by_index: tdb_fetch failed !\n"));
- goto fail;
- }
-
- count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
- locks = (struct posix_lock *)dbuf.dptr;
-
- if (count == 1) {
- tdb_delete(posix_lock_tdb, kbuf);
- } else {
- if (entry < count-1) {
- memmove(&locks[entry], &locks[entry+1], sizeof(struct posix_lock)*((count-1) - entry));
- }
- dbuf.dsize -= sizeof(struct posix_lock);
- tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
- }
-
- SAFE_FREE(dbuf.dptr);
-
- return True;
-
- fail:
-
- SAFE_FREE(dbuf.dptr);
- return False;
-}
-
-/****************************************************************************
- Add an entry into the POSIX locking tdb. We return the index number of the
- added lock (used in case we need to delete *exactly* this entry). Returns
- False on fail, True on success.
-****************************************************************************/
-
-static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, int lock_type, size_t *pentry_num)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock pl;
-
- dbuf.dptr = NULL;
- dbuf.dsize = 0;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- *pentry_num = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
- /*
- * Add new record.
- */
-
- pl.fd = fsp->fh->fd;
- pl.start = start;
- pl.size = size;
- pl.lock_type = lock_type;
-
- dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
- if (!dbuf.dptr) {
- DEBUG(0,("add_posix_lock_entry: Realloc fail !\n"));
- goto fail;
- }
-
- memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
- dbuf.dsize += sizeof(struct posix_lock);
-
- if (tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
- DEBUG(0,("add_posix_lock: Failed to add lock entry on file %s\n", fsp->fsp_name));
- goto fail;
- }
-
- SAFE_FREE(dbuf.dptr);
-
- DEBUG(10,("add_posix_lock: File %s: type = %s: start=%.0f size=%.0f: dev=%.0f inode=%.0f\n",
- fsp->fsp_name, posix_lock_type_name(lock_type), (double)start, (double)size,
- (double)fsp->dev, (double)fsp->inode ));
-
- return True;
-
- fail:
-
- SAFE_FREE(dbuf.dptr);
- return False;
-}
-
-/****************************************************************************
- Calculate if locks have any overlap at all.
-****************************************************************************/
-
-static BOOL does_lock_overlap(SMB_OFF_T start1, SMB_OFF_T size1, SMB_OFF_T start2, SMB_OFF_T size2)
-{
- if (start1 >= start2 && start1 <= start2 + size2)
- return True;
-
- if (start1 < start2 && start1 + size1 > start2)
- return True;
-
- return False;
-}
-
-/****************************************************************************
- Delete an entry from the POSIX locking tdb. Returns a copy of the entry being
- deleted and the number of records that are overlapped by this one, or -1 on error.
-****************************************************************************/
-
-static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T size, struct posix_lock *pl)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock *locks;
- size_t i, count;
- BOOL found = False;
- int num_overlapping_records = 0;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr) {
- DEBUG(10,("delete_posix_lock_entry: tdb_fetch failed !\n"));
- goto fail;
- }
-
- /* There are existing locks - find a match. */
- locks = (struct posix_lock *)dbuf.dptr;
- count = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
-
- /*
- * Search for and delete the first record that matches the
- * unlock criteria.
- */
-
- for (i=0; i<count; i++) {
- struct posix_lock *entry = &locks[i];
-
- if (entry->fd == fsp->fh->fd &&
- entry->start == start &&
- entry->size == size) {
-
- /* Make a copy */
- *pl = *entry;
-
- /* Found it - delete it. */
- if (count == 1) {
- tdb_delete(posix_lock_tdb, kbuf);
- } else {
- if (i < count-1) {
- memmove(&locks[i], &locks[i+1], sizeof(struct posix_lock)*((count-1) - i));
- }
- dbuf.dsize -= sizeof(struct posix_lock);
- tdb_store(posix_lock_tdb, kbuf, dbuf, TDB_REPLACE);
- }
- count--;
- found = True;
- break;
- }
- }
-
- if (!found)
- goto fail;
-
- /*
- * Count the number of entries that are
- * overlapped by this unlock request.
- */
-
- for (i = 0; i < count; i++) {
- struct posix_lock *entry = &locks[i];
-
- if (fsp->fh->fd == entry->fd &&
- does_lock_overlap( start, size, entry->start, entry->size))
- num_overlapping_records++;
- }
-
- DEBUG(10,("delete_posix_lock_entry: type = %s: start=%.0f size=%.0f, num_records = %d\n",
- posix_lock_type_name(pl->lock_type), (double)pl->start, (double)pl->size,
- (unsigned int)num_overlapping_records ));
-
- SAFE_FREE(dbuf.dptr);
-
- return num_overlapping_records;
-
- fail:
-
- SAFE_FREE(dbuf.dptr);
- return -1;
-}
-
/****************************************************************************
Utility function to map a lock type correctly depending on the open
mode of a file.
@@ -519,16 +55,6 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
return F_RDLCK;
}
-#if 0
- /* We no longer open files write-only. */
- else if((lock_type == READ_LOCK) && !fsp->can_read) {
- /*
- * Ditto for read locks on write only files.
- */
- DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
- return F_WRLCK;
- }
-#endif
/*
* This return should be the most normal, as we attempt
@@ -539,6 +65,15 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
}
/****************************************************************************
+ Debugging aid :-).
+****************************************************************************/
+
+static const char *posix_lock_type_name(int lock_type)
+{
+ return (lock_type == F_RDLCK) ? "READ" : "WRITE";
+}
+
+/****************************************************************************
Check to see if the given unsigned lock range is within the possible POSIX
range. Modifies the given args to be in range if possible, just returns
False if not.
@@ -608,15 +143,17 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
* We must truncate the count to less than max_positive_lock_offset.
*/
- if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset))
+ if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
count = max_positive_lock_offset;
+ }
/*
* Truncate count to end at max lock offset.
*/
- if (offset + count < 0 || offset + count > max_positive_lock_offset)
+ if (offset + count < 0 || offset + count > max_positive_lock_offset) {
count = max_positive_lock_offset - offset;
+ }
/*
* If we ate all the count, ignore this lock.
@@ -729,7 +266,6 @@ static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T
return ret;
}
-
/****************************************************************************
POSIX function to see if a file region is locked. Returns True if the
region is locked, False otherwise.
@@ -774,6 +310,416 @@ BOOL is_posix_locked(files_struct *fsp,
return True;
}
+/****************************************************************************
+ Next - the functions that deal with in memory database storing representations
+ of either Windows CIFS locks or POSIX CIFS locks.
+****************************************************************************/
+
+/* The key used in the in-memory POSIX databases. */
+
+struct lock_ref_count_key {
+ SMB_DEV_T device;
+ SMB_INO_T inode;
+ char r;
+};
+
+struct fd_key {
+ SMB_DEV_T device;
+ SMB_INO_T inode;
+};
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the fd array.
+******************************************************************/
+
+static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ static struct fd_key key;
+ TDB_DATA kbuf;
+
+ memset(&key, '\0', sizeof(key));
+ key.device = dev;
+ key.inode = inode;
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
+ return kbuf;
+}
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair for the lock ref count
+******************************************************************/
+
+static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ static struct lock_ref_count_key key;
+ TDB_DATA kbuf;
+
+ memset(&key, '\0', sizeof(key));
+ key.device = dev;
+ key.inode = inode;
+ key.r = 'r';
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
+ return kbuf;
+}
+
+/*******************************************************************
+ Convenience function to get an fd_array key from an fsp.
+******************************************************************/
+
+static TDB_DATA fd_array_key_fsp(files_struct *fsp)
+{
+ return fd_array_key(fsp->dev, fsp->inode);
+}
+
+/*******************************************************************
+ Convenience function to get a lock ref count key from an fsp.
+******************************************************************/
+
+static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp)
+{
+ return locking_ref_count_key(fsp->dev, fsp->inode);
+}
+
+/*******************************************************************
+ Create the in-memory POSIX lock databases.
+********************************************************************/
+
+BOOL posix_locking_init(int read_only)
+{
+ if (posix_pending_close_tdb) {
+ return True;
+ }
+
+ if (!posix_pending_close_tdb) {
+ posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
+ read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
+ }
+ if (!posix_pending_close_tdb) {
+ DEBUG(0,("Failed to open POSIX pending close database.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ Delete the in-memory POSIX lock databases.
+********************************************************************/
+
+BOOL posix_locking_end(void)
+{
+ if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) {
+ return False;
+ }
+ return True;
+}
+
+/****************************************************************************
+ Next - the functions that deal with storing fd's that have outstanding
+ POSIX locks when closed.
+****************************************************************************/
+
+/****************************************************************************
+ The records in posix_pending_close_tdb are composed of an array of ints
+ keyed by dev/ino pair.
+ The first int is a reference count of the number of outstanding locks on
+ all open fd's on this dev/ino pair. Any subsequent ints are the fd's that
+ were open on this dev/ino pair that should have been closed, but can't as
+ the lock ref count is non zero.
+****************************************************************************/
+
+/****************************************************************************
+ Keep a reference count of the number of Windows locks open on this dev/ino
+ pair. Creates entry if it doesn't exist.
+****************************************************************************/
+
+static void increment_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (dbuf.dptr == NULL) {
+ dbuf.dptr = (char *)SMB_MALLOC_P(int);
+ if (!dbuf.dptr) {
+ smb_panic("increment_windows_lock_ref_count: malloc fail.\n");
+ }
+ memset(dbuf.dptr, '\0', sizeof(int));
+ dbuf.dsize = sizeof(int);
+ }
+
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ lock_ref_count++;
+ memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+
+ if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+ smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n");
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+static void decrement_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ smb_panic("decrement_windows_lock_ref_count: logic error.\n");
+ }
+
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ lock_ref_count--;
+ memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+
+ if (lock_ref_count < 0) {
+ smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n");
+ }
+
+ if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+ smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n");
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+/****************************************************************************
+ Bulk delete - subtract as many locks as we've just deleted.
+****************************************************************************/
+
+void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ return;
+ }
+
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ lock_ref_count -= dcount;
+
+ if (lock_ref_count < 0) {
+ smb_panic("reduce_windows_lock_ref_count: lock_count logic error.\n");
+ }
+ memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
+
+ if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+ smb_panic("reduce_windows_lock_ref_count: tdb_store_fail.\n");
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+}
+
+/****************************************************************************
+ Fetch the lock ref count.
+****************************************************************************/
+
+static int get_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+ TDB_DATA dbuf;
+ int lock_ref_count;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+ if (!dbuf.dptr) {
+ lock_ref_count = 0;
+ } else {
+ memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ DEBUG(10,("get_windows_lock_count for file %s = %d\n",
+ fsp->fsp_name, lock_ref_count ));
+ return lock_ref_count;
+}
+
+/****************************************************************************
+ Delete a lock_ref_count entry.
+****************************************************************************/
+
+static void delete_windows_lock_ref_count(files_struct *fsp)
+{
+ TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
+
+ /* Not a bug if it doesn't exist - no locks were ever granted. */
+ tdb_delete(posix_pending_close_tdb, kbuf);
+ DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name));
+}
+
+/****************************************************************************
+ Add an fd to the pending close tdb.
+****************************************************************************/
+
+static void add_fd_to_close_entry(files_struct *fsp)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+ TDB_DATA dbuf;
+
+ dbuf.dptr = NULL;
+ dbuf.dsize = 0;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+ dbuf.dptr = (char *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
+ if (!dbuf.dptr) {
+ smb_panic("add_fd_to_close_entry: Realloc fail !\n");
+ }
+
+ memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
+ dbuf.dsize += sizeof(int);
+
+ if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
+ smb_panic("add_fd_to_close_entry: tdb_store_fail.\n");
+ }
+
+ DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n",
+ fsp->fh->fd, fsp->fsp_name ));
+
+ SAFE_FREE(dbuf.dptr);
+}
+
+/****************************************************************************
+ Remove all fd entries for a specific dev/inode pair from the tdb.
+****************************************************************************/
+
+static void delete_close_entries(files_struct *fsp)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+
+ if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
+ smb_panic("delete_close_entries: tdb_delete fail !\n");
+ }
+}
+
+/****************************************************************************
+ Get the array of POSIX pending close records for an open fsp. Caller must
+ free. Returns number of entries.
+****************************************************************************/
+
+static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
+{
+ TDB_DATA kbuf = fd_array_key_fsp(fsp);
+ TDB_DATA dbuf;
+ size_t count = 0;
+
+ *entries = NULL;
+ dbuf.dptr = NULL;
+
+ dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
+
+ if (!dbuf.dptr) {
+ return 0;
+ }
+
+ *entries = (int *)dbuf.dptr;
+ count = (size_t)(dbuf.dsize / sizeof(int));
+
+ return count;
+}
+
+/****************************************************************************
+ Deal with pending closes needed by POSIX locking support.
+ Note that posix_locking_close_file() is expected to have been called
+ to delete all locks on this fsp before this function is called.
+****************************************************************************/
+
+NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp)
+{
+ int saved_errno = 0;
+ int ret;
+ int *fd_array = NULL;
+ size_t count, i;
+
+ if (!lp_locking(fsp->conn->params) || !lp_posix_locking(conn->params)) {
+ /*
+ * No locking or POSIX to worry about or we want POSIX semantics
+ * which will lose all locks on all fd's open on this dev/inode,
+ * just close.
+ */
+ ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+ fsp->fh->fd = -1;
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (get_windows_lock_ref_count(fsp)) {
+
+ /*
+ * There are outstanding locks on this dev/inode pair on other fds.
+ * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
+ */
+
+ add_fd_to_close_entry(fsp);
+ fsp->fh->fd = -1;
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * No outstanding locks. Get the pending close fd's
+ * from the tdb and close them all.
+ */
+
+ count = get_posix_pending_close_entries(fsp, &fd_array);
+
+ if (count) {
+ DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
+
+ for(i = 0; i < count; i++) {
+ if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
+ saved_errno = errno;
+ }
+ }
+
+ /*
+ * Delete all fd's stored in the tdb
+ * for this dev/inode pair.
+ */
+
+ delete_close_entries(fsp);
+ }
+
+ SAFE_FREE(fd_array);
+
+ /* Don't need a lock ref count on this dev/ino anymore. */
+ delete_windows_lock_ref_count(fsp);
+
+ /*
+ * Finally close the fd associated with this fsp.
+ */
+
+ ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+
+ if (ret == 0 && saved_errno != 0) {
+ errno = saved_errno;
+ ret = -1;
+ }
+
+ fsp->fh->fd = -1;
+
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Next - the functions that deal with the mapping CIFS Windows locks onto
+ the underlying system POSIX locks.
+****************************************************************************/
+
/*
* Structure used when splitting a lock range
* into a POSIX lock range. Doubly linked list.
@@ -792,22 +738,14 @@ struct lock_list {
understand it :-).
****************************************************************************/
-static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhead, files_struct *fsp)
+static struct lock_list *posix_lock_list(TALLOC_CTX *ctx,
+ struct lock_list *lhead,
+ const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */
+ files_struct *fsp,
+ const struct lock_struct *plocks,
+ int num_locks)
{
- TDB_DATA kbuf = locking_key_fsp(fsp);
- TDB_DATA dbuf;
- struct posix_lock *locks;
- size_t num_locks, i;
-
- dbuf.dptr = NULL;
-
- dbuf = tdb_fetch(posix_lock_tdb, kbuf);
-
- if (!dbuf.dptr)
- return lhead;
-
- locks = (struct posix_lock *)dbuf.dptr;
- num_locks = (size_t)(dbuf.dsize / sizeof(struct posix_lock));
+ int i;
/*
* Check the current lock list on this dev/inode pair.
@@ -818,10 +756,19 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
(double)lhead->start, (double)lhead->size ));
for (i=0; i<num_locks && lhead; i++) {
-
- struct posix_lock *lock = &locks[i];
+ const struct lock_struct *lock = &plocks[i];
struct lock_list *l_curr;
+ /* Ignore all but read/write locks. */
+ if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
+ continue;
+ }
+
+ /* Ignore locks not owned by this process. */
+ if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) {
+ continue;
+ }
+
/*
* Walk the lock list, checking for overlaps. Note that
* the lock list can expand within this loop if the current
@@ -830,13 +777,13 @@ static struct lock_list *posix_lock_list(TALLOC_CTX *ctx, struct lock_list *lhea
for (l_curr = lhead; l_curr;) {
- DEBUG(10,("posix_lock_list: lock: fd=%d: start=%.0f,size=%.0f:type=%s", lock->fd,
+ DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum,
(double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) ));
if ( (l_curr->start >= (lock->start + lock->size)) ||
(lock->start >= (l_curr->start + l_curr->size))) {
- /* No overlap with this lock - leave this range alone. */
+ /* No overlap with existing lock - leave this range alone. */
/*********************************************
+---------+
| l_curr |
@@ -850,7 +797,7 @@ OR....
+---------+
**********************************************/
- DEBUG(10,("no overlap case.\n" ));
+ DEBUG(10,(" no overlap case.\n" ));
l_curr = l_curr->next;
@@ -858,8 +805,8 @@ OR....
(l_curr->start + l_curr->size <= lock->start + lock->size) ) {
/*
- * This unlock is completely overlapped by this existing lock range
- * and thus should have no effect (not be unlocked). Delete it from the list.
+ * This range is completely overlapped by this existing lock range
+ * and thus should have no effect. Delete it from the list.
*/
/*********************************************
+---------+
@@ -872,11 +819,12 @@ OR....
/* Save the next pointer */
struct lock_list *ul_next = l_curr->next;
- DEBUG(10,("delete case.\n" ));
+ DEBUG(10,(" delete case.\n" ));
DLIST_REMOVE(lhead, l_curr);
- if(lhead == NULL)
+ if(lhead == NULL) {
break; /* No more list... */
+ }
l_curr = ul_next;
@@ -885,7 +833,7 @@ OR....
(l_curr->start + l_curr->size > lock->start + lock->size) ) {
/*
- * This unlock overlaps the existing lock range at the high end.
+ * This range overlaps the existing lock range at the high end.
* Truncate by moving start to existing range end and reducing size.
*/
/*********************************************
@@ -904,7 +852,7 @@ BECOMES....
l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);
l_curr->start = lock->start + lock->size;
- DEBUG(10,("truncate high case: start=%.0f,size=%.0f\n",
+ DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n",
(double)l_curr->start, (double)l_curr->size ));
l_curr = l_curr->next;
@@ -914,7 +862,7 @@ BECOMES....
(l_curr->start + l_curr->size <= lock->start + lock->size) ) {
/*
- * This unlock overlaps the existing lock range at the low end.
+ * This range overlaps the existing lock range at the low end.
* Truncate by reducing size.
*/
/*********************************************
@@ -932,7 +880,7 @@ BECOMES....
l_curr->size = lock->start - l_curr->start;
- DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n",
+ DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n",
(double)l_curr->start, (double)l_curr->size ));
l_curr = l_curr->next;
@@ -940,10 +888,10 @@ BECOMES....
} else if ( (l_curr->start < lock->start) &&
(l_curr->start + l_curr->size > lock->start + lock->size) ) {
/*
- * Worst case scenario. Unlock request completely overlaps an existing
+ * Worst case scenario. Range completely overlaps an existing
* lock range. Split the request into two, push the new (upper) request
- * into the dlink list, and continue with the entry after ul_new (as we
- * know that ul_new will not overlap with this lock).
+ * into the dlink list, and continue with the entry after l_new (as we
+ * know that l_new will not overlap with this lock).
*/
/*********************************************
+---------------------------+
@@ -971,7 +919,7 @@ BECOMES.....
/* Truncate the l_curr. */
l_curr->size = lock->start - l_curr->start;
- DEBUG(10,("split case: curr: start=%.0f,size=%.0f \
+ DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \
new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size,
(double)l_new->start, (double)l_new->size ));
@@ -1003,34 +951,33 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size,
} /* end for ( l_curr = lhead; l_curr;) */
} /* end for (i=0; i<num_locks && ul_head; i++) */
- SAFE_FREE(dbuf.dptr);
-
return lhead;
}
/****************************************************************************
POSIX function to acquire a lock. Returns True if the
lock could be granted, False if not.
- TODO -- Fix POSIX lock flavour semantics.
****************************************************************************/
-BOOL set_posix_lock(files_struct *fsp,
+BOOL set_posix_lock_windows_flavour(files_struct *fsp,
SMB_BIG_UINT u_offset,
SMB_BIG_UINT u_count,
enum brl_type lock_type,
- enum brl_flavour lock_flav)
+ const struct lock_context *lock_ctx,
+ const struct lock_struct *plocks,
+ int num_locks,
+ int *errno_ret)
{
SMB_OFF_T offset;
SMB_OFF_T count;
+ int posix_lock_type = map_posix_lock_type(fsp,lock_type);
BOOL ret = True;
- size_t entry_num = 0;
size_t lock_count;
TALLOC_CTX *l_ctx = NULL;
struct lock_list *llist = NULL;
struct lock_list *ll = NULL;
- int posix_lock_type = map_posix_lock_type(fsp,lock_type);
- DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",
+ DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
/*
@@ -1038,8 +985,10 @@ BOOL set_posix_lock(files_struct *fsp,
* pretend it was successful.
*/
- if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+ if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
+ increment_windows_lock_ref_count(fsp);
return True;
+ }
/*
* Windows is very strange. It allows read locks to be overlayed
@@ -1056,21 +1005,18 @@ BOOL set_posix_lock(files_struct *fsp,
* READ LOCK: start =0, len = 10 - OK
*
* Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but
- * would leave a single read lock over the 0-14 region. In order to
- * re-create Windows semantics mapped to POSIX locks, we create multiple TDB
- * entries, one for each overlayed lock request. We are guarenteed by the brlock
- * semantics that if a write lock is added, then it will be first in the array.
+ * would leave a single read lock over the 0-14 region.
*/
if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
- DEBUG(0,("set_posix_lock: unable to init talloc context.\n"));
- return True; /* Not a fatal error. */
+ DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
+ return False;
}
if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {
- DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n"));
+ DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
talloc_destroy(l_ctx);
- return True; /* Not a fatal error. */
+ return False;
}
/*
@@ -1092,19 +1038,12 @@ BOOL set_posix_lock(files_struct *fsp,
* POSIX locks.
*/
- llist = posix_lock_list(l_ctx, llist, fsp);
-
- /*
- * Now we have the list of ranges to lock it is safe to add the
- * entry into the POSIX lock tdb. We take note of the entry we
- * added here in case we have to remove it on POSIX lock fail.
- */
-
- if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) {
- DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n"));
- talloc_destroy(l_ctx);
- return False;
- }
+ llist = posix_lock_list(l_ctx,
+ llist,
+ lock_ctx, /* Lock context llist belongs to. */
+ fsp,
+ plocks,
+ num_locks);
/*
* Add the POSIX locks on the list of ranges returned.
@@ -1116,11 +1055,12 @@ BOOL set_posix_lock(files_struct *fsp,
offset = ll->start;
count = ll->size;
- DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
+ DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
- DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
+ *errno_ret = errno;
+ DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
ret = False;
break;
@@ -1137,17 +1077,14 @@ BOOL set_posix_lock(files_struct *fsp,
offset = ll->start;
count = ll->size;
- DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
+ DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);
}
-
- /*
- * Remove the tdb entry for this lock.
- */
-
- delete_posix_lock_entry_by_index(fsp,entry_num);
+ } else {
+ /* Remember the number of Windows locks we have on this dev/ino pair. */
+ increment_windows_lock_ref_count(fsp);
}
talloc_destroy(l_ctx);
@@ -1159,7 +1096,13 @@ BOOL set_posix_lock(files_struct *fsp,
lock could be released, False if not.
****************************************************************************/
-BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
+BOOL release_posix_lock_windows_flavour(files_struct *fsp,
+ SMB_BIG_UINT u_offset,
+ SMB_BIG_UINT u_count,
+ enum brl_type deleted_lock_type,
+ const struct lock_context *lock_ctx,
+ const struct lock_struct *plocks,
+ int num_locks)
{
SMB_OFF_T offset;
SMB_OFF_T count;
@@ -1167,56 +1110,31 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
TALLOC_CTX *ul_ctx = NULL;
struct lock_list *ulist = NULL;
struct lock_list *ul = NULL;
- struct posix_lock deleted_lock;
- int num_overlapped_entries;
- DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",
+ DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n",
fsp->fsp_name, (double)u_offset, (double)u_count ));
+ /* Remember the number of Windows locks we have on this dev/ino pair. */
+ decrement_windows_lock_ref_count(fsp);
+
/*
* If the requested lock won't fit in the POSIX range, we will
* pretend it was successful.
*/
- if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+ if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
return True;
-
- /*
- * We treat this as one unlock request for POSIX accounting purposes even
- * if it may later be split into multiple smaller POSIX unlock ranges.
- * num_overlapped_entries is the number of existing locks that have any
- * overlap with this unlock request.
- */
-
- num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock);
-
- if (num_overlapped_entries == -1) {
- smb_panic("release_posix_lock: unable find entry to delete !\n");
- }
-
- /*
- * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was
- * a POSIX write lock, then before doing the unlock we need to downgrade
- * the POSIX lock to a read lock. This allows any overlapping read locks
- * to be atomically maintained.
- */
-
- if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) {
- if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
- DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) ));
- return False;
- }
}
if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
- DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));
- return True; /* Not a fatal error. */
+ DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
+ return False;
}
if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
- DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n"));
+ DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
talloc_destroy(ul_ctx);
- return True; /* Not a fatal error. */
+ return False;
}
/*
@@ -1239,7 +1157,33 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
* unlocks are performed.
*/
- ulist = posix_lock_list(ul_ctx, ulist, fsp);
+ ulist = posix_lock_list(ul_ctx,
+ ulist,
+ lock_ctx, /* Lock context ulist belongs to. */
+ fsp,
+ plocks,
+ num_locks);
+
+ /*
+ * If there were any overlapped entries (list is > 1 or size or start have changed),
+ * and the lock_type we just deleted from
+ * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade
+ * the POSIX lock to a read lock. This allows any overlapping read locks
+ * to be atomically maintained.
+ */
+
+ if (deleted_lock_type == WRITE_LOCK &&
+ (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) {
+
+ DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n",
+ (double)offset, (double)count ));
+
+ if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
+ DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
+ talloc_destroy(ul_ctx);
+ return False;
+ }
+ }
/*
* Release the POSIX locks on the list of ranges returned.
@@ -1249,129 +1193,148 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
offset = ulist->start;
count = ulist->size;
- DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
+ DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n",
(double)offset, (double)count ));
- if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK))
+ if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
ret = False;
+ }
}
talloc_destroy(ul_ctx);
-
return ret;
}
/****************************************************************************
- Remove all lock entries for a specific dev/inode pair from the tdb.
+ Next - the functions that deal with mapping CIFS POSIX locks onto
+ the underlying system POSIX locks.
****************************************************************************/
-static void delete_posix_lock_entries(files_struct *fsp)
-{
- TDB_DATA kbuf = locking_key_fsp(fsp);
-
- if (tdb_delete(posix_lock_tdb, kbuf) == -1)
- DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));
-}
-
/****************************************************************************
- Debug function.
+ POSIX function to acquire a lock. Returns True if the
+ lock could be granted, False if not.
+ As POSIX locks don't stack or conflict (they just overwrite)
+ we can map the requested lock directly onto a system one. We
+ know it doesn't conflict with locks on other contexts as the
+ upper layer would have refused it.
****************************************************************************/
-static void dump_entry(struct posix_lock *pl)
+BOOL set_posix_lock_posix_flavour(files_struct *fsp,
+ SMB_BIG_UINT u_offset,
+ SMB_BIG_UINT u_count,
+ enum brl_type lock_type,
+ int *errno_ret)
{
- DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
- (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
+ SMB_OFF_T offset;
+ SMB_OFF_T count;
+ int posix_lock_type = map_posix_lock_type(fsp,lock_type);
+
+ DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
+ fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
+
+ /*
+ * If the requested lock won't fit in the POSIX range, we will
+ * pretend it was successful.
+ */
+
+ if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
+ return True;
+ }
+
+ if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
+ *errno_ret = errno;
+ DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
+ posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
+ return False;
+ }
+ return True;
}
/****************************************************************************
- Remove any locks on this fd. Called from file_close().
+ POSIX function to release a lock. Returns True if the
+ lock could be released, False if not.
+ We are given a complete lock state from the upper layer which is what the lock
+ state should be after the unlock has already been done, so what
+ we do is punch out holes in the unlock range where locks owned by this process
+ have a different lock context.
****************************************************************************/
-void posix_locking_close_file(files_struct *fsp)
+BOOL release_posix_lock_posix_flavour(files_struct *fsp,
+ SMB_BIG_UINT u_offset,
+ SMB_BIG_UINT u_count,
+ const struct lock_context *lock_ctx,
+ const struct lock_struct *plocks,
+ int num_locks)
{
- struct posix_lock *entries = NULL;
- size_t count, i;
+ BOOL ret = True;
+ SMB_OFF_T offset;
+ SMB_OFF_T count;
+ TALLOC_CTX *ul_ctx = NULL;
+ struct lock_list *ulist = NULL;
+ struct lock_list *ul = NULL;
+
+ DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n",
+ fsp->fsp_name, (double)u_offset, (double)u_count ));
/*
- * Optimization for the common case where we are the only
- * opener of a file. If all fd entries are our own, we don't
- * need to explicitly release all the locks via the POSIX functions,
- * we can just remove all the entries in the tdb and allow the
- * close to remove the real locks.
+ * If the requested lock won't fit in the POSIX range, we will
+ * pretend it was successful.
*/
- count = get_posix_lock_entries(fsp, &entries);
-
- if (count == 0) {
- DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));
- return;
+ if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
+ return True;
}
- for (i = 0; i < count; i++) {
- if (entries[i].fd != fsp->fh->fd )
- break;
-
- dump_entry(&entries[i]);
+ if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
+ DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
+ return False;
}
- if (i == count) {
- /* All locks are ours. */
- DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n",
- fsp->fsp_name, (unsigned int)count ));
- SAFE_FREE(entries);
- delete_posix_lock_entries(fsp);
- return;
+ if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
+ DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
+ talloc_destroy(ul_ctx);
+ return False;
}
/*
- * Difficult case. We need to delete all our locks, whilst leaving
- * all other POSIX locks in place.
+ * Create the initial list entry containing the
+ * lock we want to remove.
+ */
+
+ ZERO_STRUCTP(ul);
+ ul->start = offset;
+ ul->size = count;
+
+ DLIST_ADD(ulist, ul);
+
+ /*
+ * Walk the given array creating a linked list
+ * of unlock requests.
*/
- for (i = 0; i < count; i++) {
- struct posix_lock *pl = &entries[i];
- if (pl->fd == fsp->fh->fd)
- release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
- }
- SAFE_FREE(entries);
-}
+ ulist = posix_lock_list(ul_ctx,
+ ulist,
+ lock_ctx, /* Lock context ulist belongs to. */
+ fsp,
+ plocks,
+ num_locks);
-/*******************************************************************
- Create the in-memory POSIX lock databases.
-********************************************************************/
+ /*
+ * Release the POSIX locks on the list of ranges returned.
+ */
-BOOL posix_locking_init(int read_only)
-{
- if (posix_lock_tdb && posix_pending_close_tdb)
- return True;
-
- if (!posix_lock_tdb)
- posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
- read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
- if (!posix_lock_tdb) {
- DEBUG(0,("Failed to open POSIX byte range locking database.\n"));
- return False;
- }
- if (!posix_pending_close_tdb)
- posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
- read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
- if (!posix_pending_close_tdb) {
- DEBUG(0,("Failed to open POSIX pending close database.\n"));
- return False;
- }
+ for(; ulist; ulist = ulist->next) {
+ offset = ulist->start;
+ count = ulist->size;
- return True;
-}
+ DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n",
+ (double)offset, (double)count ));
-/*******************************************************************
- Delete the in-memory POSIX lock databases.
-********************************************************************/
+ if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
+ ret = False;
+ }
+ }
-BOOL posix_locking_end(void)
-{
- if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0)
- return False;
- if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0)
- return False;
- return True;
+ talloc_destroy(ul_ctx);
+ return ret;
}
diff --git a/source/modules/README-gpfs-acl.txt b/source/modules/README-gpfs-acl.txt
new file mode 100644
index 00000000000..49f3259c1e6
--- /dev/null
+++ b/source/modules/README-gpfs-acl.txt
@@ -0,0 +1,82 @@
+This patch has been taken against SAMBA_3_0 Release 20028.
+
+The patch basically moves the GPFS-ACL functionalities into the new GPFS VFS module( vfs_gpfs ).
+
+Please read SAMBA_3_0/source/modules/README.nfs4acls.txt - generalised README file on Samba support for NFS4-ACLS.
+This README file is specific for GPFS only.
+
+Configuring GPFS ACL support
+===============================
+
+Binary: (default install path is [samba]/lib/vfs/)
+- gpfs.so
+
+Its compiled by default, no additional configure option needed.
+
+To enable/use/load this module, include "vfs objects = gpfs" in the smb.conf file under concerned share-name.
+
+Example of smb.conf:
+
+[smbtest]
+path = /gpfs-test
+vfs objects = gpfs
+nfs4: mode = special
+nfs4: chown = yes
+nfs4: acedup = merge
+
+Adding "vfs objects = gpfs" to a share should be done only in case when NFS4 is really supported by the filesystem.
+(Otherwise you may get performance loss.)
+
+==================================================
+Below are some limitations listed for this module:
+==================================================
+1. When a child file or child directory is created, the results are a bit different from windows as specified below:
+
+Eg: Prent directory is set to have 2 ACES - full access for owner and everyone
+
+Default ACL for Windows: 2 aces: allow ACE for owner and everyone
+Default ACL for GPFS: 6 aces: allow and deny ACEs for owner, group and everyone
+
+The below mentioned inheritance flags and its combinations are applied only to the owner ACE and not to everyone ACE
+
+"fi"------>File Inherit
+"di"------>Directory Inherit
+"oi"------>Inherit Only
+
+
+Parent dir: no inheritance flag set
+ Windows: index=0: GPFS(special mode): index=0: GPFS(simple mode): index=0:
+child File: default acl: 2 aces child file: default acl: 6 aces child file: default acl: 6 aces
+child dir: default acl: 2 aces child dir: default acl: 6 aces child dir: default acl: 6 aces
+
+
+Parent dir: "fi" flag set
+ Windows: index=1: GPFS(special mode): index=1: GPFS(simple mode): index=1:
+child file: no flag set child file: "fi" flag set child file: default acl: 6 aces
+child dir: "fioi" flag set child dir: "fi" flag set child dir: "fi" flag set
+
+
+Parent dir: "di" flag set
+ Windows: index=2: GPFS(special mode): index=2: GPFS(simple mode): index=2:
+child file: default acl: 2 aces child file: default acl: 6 aces child file: default acl: 6 aces
+
+
+Parent dir: "fidi" flag set
+ Windows: index=3: GPFS(special mode): index=3: GPFS(simple mode): index=3:
+child file: no flag set child file: "fidi" flag set child file: default acl: 6 aces
+
+
+Parent dir: "fioi" flag set
+ Windows: index=4: GPFS(special mode): index=4: GPFS(simple mode): index=4:
+child file: no flag set child file: "fi" flag set child file: default acl: 6 aces
+child dir: "fioi" flag set child dir: "fi" flag set child dir: "fi" flag set
+
+
+Parent dir: "dioi" flag set
+ Windows: index=5: GPFS(special mode): index=5: GPFS(simple mode): index=5:
+child file: default acl: 2 aces child file: default acl: 6 aces child file: default acl: 6 aces
+
+
+Parent dir: "fidioi" flag set
+ Windows: index=6: GPFS(special mode): index=6: GPFS(simple mode): index=6:
+child file: no flag set child file: "fidi" flag set child file: default acl: 6 aces
diff --git a/source/modules/README.nfs4acls.txt b/source/modules/README.nfs4acls.txt
new file mode 100644
index 00000000000..1cb08877d32
--- /dev/null
+++ b/source/modules/README.nfs4acls.txt
@@ -0,0 +1,82 @@
+Configuring NFS4 ACLs in Samba3
+===============================
+Created: Peter Somogyi, 2006-JUN-06
+Last modified: Peter Somogyi, 2006-JUL-20
+Revision no.: 4
+-------------------------------
+
+
+Parameters in smb.conf:
+=======================
+
+Each parameter must have a prefix "nfs4:".
+Each one affects the behaviour only when _setting_ an acl on a file/dir:
+
+mode = [simple|special]
+- simple: don't use OWNER@ and GROUP@ special IDs in ACEs. - default
+- special: use OWNER@ and GROUP@ special IDs in ACEs instead of simple user&group ids.
+Note: EVERYONE@ is always processed (if found such an ACE).
+Note2: special mode will have side effect when _only_ chown is performed. Later this may be worked out.
+
+Use "simple" mode when the share is used mainly by windows users and unix side is not significant. You will loose unix bits in this case.
+It's strongly advised setting "store dos attributes = yes" in smb.conf.
+
+chown = [true|false]
+- true => enable changing owner and group - default.
+- false => disable support for changing owner or group
+
+acedup = [dontcare|reject|ignore|merge]
+- dontcare: copy ACEs as they come, don't care with "duplicate" records. Default.
+- reject: stop operation, exit acl setter operation with an error
+- ignore: don't include the second matching ACE
+- merge: OR 2 ace.flag fields and 2 ace.mask fields of the 2 duplicate ACEs into 1 ACE
+
+Two ACEs are considered here "duplicate" when their type and id fields are matching.
+
+Example:
+
+[smbtest]
+path = /tests/psomogyi/smbtest
+writable = yes
+vfs objects = aixacl2
+nfs4: mode = special
+nfs4: chown = yes
+nfs4: acedup = merge
+
+Configuring AIX ACL support
+==============================
+
+Binaries: (default install path is [samba]/lib/vfs/)
+- aixacl.so: provides AIXC ACL support only, can be compiled and works on all AIX platforms
+- aixacl2.so: provides AIXC and JFS2-NFS4 ACL support, can be compiled and works only under AIX 5.3 and newer.
+NFS4 acl currently has support only under JFS2 (ext. attr. format must be set to v2).
+aixacl2.so always detects support for NFS4 acls and redirects to POSIX ACL handling automatically when NFS4 is not supported for a path.
+
+Adding "vfs objects = aixacl2" to a share should be done only in case when NFS4 is really supported by the filesystem.
+(Otherwise you may get performance loss.)
+
+For configuration see also the example above.
+
+General notes
+=============
+
+NFS4 handling logic is separated from AIX/jfs2 ACL parsing.
+
+Samba and its VFS modules dosn't reorder ACEs. Windows clients do that (and the smbcacl tool). MSDN also says deny ACEs must come first.
+NFS4 ACL's validity is checked by the system API, not by Samba.
+NFS4 ACL rights are enforced by the OS or filesystem, not by Samba.
+
+The flag INHERITED_ACE is never set (not required, as doesn't do WinNT/98/me, only since Win2k).
+Win2k GUI behaves strangely when detecting inheritance (sometimes it doesn't detect,
+but after adding an ace it shows that - it's some GUI error).
+
+Unknown (unmappable) SIDs are not accepted.
+
+TODOs
+=====
+- Creator Owner & Group SID handling (same way as posix)
+- the 4 generic rights bits support (GENERIC_RIGHT_READ_ACCESS, WRITE, EXEC, ALL)
+- chown & no ACL, but we have ONWER@ and GROUP@
+- DIALUP, ANONYMOUS, ... builtin SIDs
+- audit & alarm support - in theory it's forwarded so it should work, but currently there's no platform which supports them to test
+- support for a real NFS4 client (we don't have an accepted API yet)
diff --git a/source/modules/charset_macosxfs.c b/source/modules/charset_macosxfs.c
index 6f50d879ba4..3e5e2ff8bd2 100644
--- a/source/modules/charset_macosxfs.c
+++ b/source/modules/charset_macosxfs.c
@@ -62,7 +62,7 @@ static inline void *resize_buffer (void *buffer, size_t *size, size_t newsize)
{
if (newsize > *size) {
*size = newsize + 128;
- buffer = realloc(buffer, *size);
+ buffer = SMB_REALLOC(buffer, *size);
}
return buffer;
}
@@ -594,7 +594,7 @@ static struct charset_functions macosxfs_encoding_functions = {
"MACOSXFS", macosxfs_encoding_pull, macosxfs_encoding_push
};
-NTSTATUS init_module(void)
+NTSTATUS charset_macosxfs_init(void)
{
return smb_register_charset(&macosxfs_encoding_functions);
}
diff --git a/source/modules/gpfs.c b/source/modules/gpfs.c
new file mode 100644
index 00000000000..19050ad3ca5
--- /dev/null
+++ b/source/modules/gpfs.c
@@ -0,0 +1,236 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Provide a connection to GPFS specific features
+ * 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"
+
+#ifdef HAVE_GPFS
+
+#include "gpfs_gpl.h"
+
+static void *libgpfs_handle = NULL;
+
+static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny);
+static int (*gpfs_set_lease_fn)(int fd, unsigned int leaseType);
+static int (*gpfs_getacl_fn)(char *pathname, int flags, void *acl);
+static int (*gpfs_putacl_fn)(char *pathname, int flags, void *acl);
+
+
+BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
+ uint32 share_access)
+{
+ unsigned int allow = GPFS_SHARE_NONE;
+ unsigned int deny = GPFS_DENY_NONE;
+ int result;
+
+ if (gpfs_set_share_fn == NULL) {
+ return False;
+ }
+
+ if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) {
+ /* No real file, don't disturb */
+ return True;
+ }
+
+ allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA|
+ DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0;
+ allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ?
+ GPFS_SHARE_READ : 0;
+
+ if (allow == GPFS_SHARE_NONE) {
+ DEBUG(10, ("special case am=no_access:%x\n",access_mask));
+ }
+ else {
+ deny |= (share_access & FILE_SHARE_WRITE) ?
+ 0 : GPFS_DENY_WRITE;
+ deny |= (share_access & (FILE_SHARE_READ)) ?
+ 0 : GPFS_DENY_READ;
+ }
+ DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n",
+ access_mask, allow, share_access, deny));
+
+ result = gpfs_set_share_fn(fsp->fh->fd, allow, deny);
+ if (result != 0) {
+ if (errno == ENOSYS) {
+ DEBUG(5, ("VFS module vfs_gpfs loaded, but no gpfs "
+ "support has been compiled into Samba. Allowing access\n"));
+ return True;
+ } else {
+ DEBUG(10, ("gpfs_set_share failed: %s\n",
+ strerror(errno)));
+ }
+ }
+
+ return (result == 0);
+}
+
+int set_gpfs_lease(int fd, int leasetype)
+{
+ int gpfs_type = GPFS_LEASE_NONE;
+
+ if (gpfs_set_lease_fn == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (leasetype == F_RDLCK) {
+ gpfs_type = GPFS_LEASE_READ;
+ }
+ if (leasetype == F_WRLCK) {
+ gpfs_type = GPFS_LEASE_WRITE;
+ }
+ return gpfs_set_lease_fn(fd, gpfs_type);
+}
+
+int smbd_gpfs_getacl(char *pathname, int flags, void *acl)
+{
+ if (gpfs_getacl_fn == NULL) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return gpfs_getacl_fn(pathname, flags, acl);
+}
+
+int smbd_gpfs_putacl(char *pathname, int flags, void *acl)
+{
+ if (gpfs_putacl_fn == NULL) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return gpfs_putacl_fn(pathname, flags, acl);
+}
+
+void init_gpfs(void)
+{
+ if (libgpfs_handle != NULL) {
+ return;
+ }
+
+ libgpfs_handle = sys_dlopen("libgpfs_gpl.so", RTLD_LAZY);
+
+ if (libgpfs_handle == NULL) {
+ DEBUG(10, ("sys_dlopen for libgpfs_gpl failed: %s\n",
+ strerror(errno)));
+ return;
+ }
+
+ DEBUG(10, ("libgpfs_gpl.so loaded\n"));
+
+ gpfs_set_share_fn = sys_dlsym(libgpfs_handle, "gpfs_set_share");
+ if (gpfs_set_share_fn == NULL) {
+ DEBUG(3, ("libgpfs_gpl.so does not contain the symbol "
+ "'gpfs_set_share'\n"));
+ sys_dlclose(libgpfs_handle);
+
+ /* leave libgpfs_handle != NULL around, no point
+ in trying twice */
+ gpfs_set_share_fn = NULL;
+ gpfs_set_lease_fn = NULL;
+ gpfs_getacl_fn = NULL;
+ gpfs_putacl_fn = NULL;
+ return;
+ }
+
+ gpfs_set_lease_fn = sys_dlsym(libgpfs_handle, "gpfs_set_lease");
+ if (gpfs_set_lease_fn == NULL) {
+ DEBUG(3, ("libgpfs_gpl.so does not contain the symbol "
+ "'gpfs_set_lease'\n"));
+ sys_dlclose(libgpfs_handle);
+
+ /* leave libgpfs_handle != NULL around, no point
+ in trying twice */
+ gpfs_set_share_fn = NULL;
+ gpfs_set_lease_fn = NULL;
+ gpfs_getacl_fn = NULL;
+ gpfs_putacl_fn = NULL;
+ return;
+ }
+
+ gpfs_getacl_fn = sys_dlsym(libgpfs_handle, "gpfs_getacl");
+ if (gpfs_getacl_fn == NULL) {
+ DEBUG(3, ("libgpfs_gpl.so does not contain the symbol "
+ "'gpfs_getacl'\n"));
+ sys_dlclose(libgpfs_handle);
+
+ /* leave libgpfs_handle != NULL around, no point
+ in trying twice */
+ gpfs_set_share_fn = NULL;
+ gpfs_set_lease_fn = NULL;
+ gpfs_getacl_fn = NULL;
+ gpfs_putacl_fn = NULL;
+ return;
+ }
+
+ gpfs_putacl_fn = sys_dlsym(libgpfs_handle, "gpfs_putacl");
+ if (gpfs_putacl_fn == NULL) {
+ DEBUG(3, ("libgpfs_gpl.so does not contain the symbol "
+ "'gpfs_putacl'\n"));
+ sys_dlclose(libgpfs_handle);
+
+ /* leave libgpfs_handle != NULL around, no point
+ in trying twice */
+ gpfs_set_share_fn = NULL;
+ gpfs_set_lease_fn = NULL;
+ gpfs_getacl_fn = NULL;
+ gpfs_putacl_fn = NULL;
+ return;
+ }
+
+}
+
+#else
+
+int set_gpfs_lease(int snum, int leasetype)
+{
+ DEBUG(0, ("'VFS module smbgpfs loaded, without gpfs support compiled\n"));
+
+ /* We need to indicate that no GPFS is around by returning ENOSYS, so
+ * that the normal linux kernel oplock code is called. */
+ errno = ENOSYS;
+ return -1;
+}
+
+BOOL set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
+ uint32 share_access)
+{
+ DEBUG(0, ("VFS module - smbgpfs.so loaded, without gpfs support compiled\n"));
+ /* Don't disturb but complain */
+ return True;
+}
+
+int smbd_gpfs_getacl(char *pathname, int flags, void *acl)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int smbd_gpfs_putacl(char *pathname, int flags, void *acl)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+void init_gpfs(void)
+{
+ return;
+}
+
+#endif /* HAVE_GPFS */
diff --git a/source/modules/nfs4_acls.c b/source/modules/nfs4_acls.c
new file mode 100644
index 00000000000..91ebba1f588
--- /dev/null
+++ b/source/modules/nfs4_acls.c
@@ -0,0 +1,668 @@
+/*
+ * NFS4 ACL handling
+ *
+ * Copyright (C) Jim McDonough, 2006
+ *
+ * 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 "nfs4_acls.h"
+
+#define SMBACL4_PARAM_TYPE_NAME "nfs4"
+
+#define SMB_ACE4_INT_MAGIC 0x76F8A967
+typedef struct _SMB_ACE4_INT_T
+{
+ uint32 magic;
+ SMB_ACE4PROP_T prop;
+ void *next;
+} SMB_ACE4_INT_T;
+
+#define SMB_ACL4_INT_MAGIC 0x29A3E792
+typedef struct _SMB_ACL4_INT_T
+{
+ uint32 magic;
+ uint32 naces;
+ SMB_ACE4_INT_T *first;
+ SMB_ACE4_INT_T *last;
+} SMB_ACL4_INT_T;
+
+extern struct current_user current_user;
+extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid);
+extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp,
+ uint32 security_info_sent, SEC_DESC *psd);
+
+static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl)
+{
+ SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
+ if (acl==NULL)
+ {
+ DEBUG(2, ("acl is NULL\n"));
+ errno = EINVAL;
+ return NULL;
+ }
+ if (aclint->magic!=SMB_ACL4_INT_MAGIC)
+ {
+ DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic));
+ errno = EINVAL;
+ return NULL;
+ }
+ return aclint;
+}
+
+static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
+{
+ SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace;
+ if (ace==NULL)
+ {
+ DEBUG(2, ("ace is NULL\n"));
+ errno = EINVAL;
+ return NULL;
+ }
+ if (aceint->magic!=SMB_ACE4_INT_MAGIC)
+ {
+ DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic));
+ errno = EINVAL;
+ return NULL;
+ }
+ return aceint;
+}
+
+SMB4ACL_T *smb_create_smb4acl(void)
+{
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+ SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T));
+ if (acl==NULL)
+ {
+ DEBUG(0, ("talloc_size failed\n"));
+ errno = ENOMEM;
+ return NULL;
+ }
+ memset(acl, 0, sizeof(SMB_ACL4_INT_T));
+ acl->magic = SMB_ACL4_INT_MAGIC;
+ /* acl->first, last = NULL not needed */
+ return (SMB4ACL_T *)acl;
+}
+
+SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
+{
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+ SMB_ACE4_INT_T *ace;
+
+ ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T));
+ if (ace==NULL)
+ {
+ DEBUG(0, ("talloc_size failed\n"));
+ errno = ENOMEM;
+ return NULL;
+ }
+ memset(ace, 0, sizeof(SMB_ACE4_INT_T));
+ ace->magic = SMB_ACE4_INT_MAGIC;
+ /* ace->next = NULL not needed */
+ memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T));
+
+ if (aclint->first==NULL)
+ {
+ aclint->first = ace;
+ aclint->last = ace;
+ } else {
+ aclint->last->next = (void *)ace;
+ aclint->last = ace;
+ }
+ aclint->naces++;
+
+ return (SMB4ACE_T *)ace;
+}
+
+SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace)
+{
+ SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
+ if (aceint==NULL)
+ return NULL;
+
+ return &aceint->prop;
+}
+
+SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace)
+{
+ SMB_ACE4_INT_T *aceint = get_validated_aceint(ace);
+ if (aceint==NULL)
+ return NULL;
+
+ return (SMB4ACE_T *)aceint->next;
+}
+
+SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl)
+{
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ if (aclint==NULL)
+ return NULL;
+
+ return (SMB4ACE_T *)aclint->first;
+}
+
+uint32 smb_get_naces(SMB4ACL_T *acl)
+{
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ if (aclint==NULL)
+ return 0;
+
+ return aclint->naces;
+}
+
+static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
+{
+ memset(psbuf, 0, sizeof(SMB_STRUCT_STAT));
+ if (fsp->is_directory || fsp->fh->fd == -1) {
+ /* Get the stat struct for the owner info. */
+ if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0)
+ {
+ DEBUG(8, ("SMB_VFS_STAT failed with error %s\n",
+ strerror(errno)));
+ return -1;
+ }
+ } else {
+ if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0)
+ {
+ DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
+ strerror(errno)));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */
+ DOM_SID *psid_owner, /* in */
+ DOM_SID *psid_group, /* in */
+ SEC_ACE **ppnt_ace_list, /* out */
+ int *pgood_aces /* out */
+)
+{
+ SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
+ SMB_ACE4_INT_T *aceint;
+ SEC_ACE *nt_ace_list = NULL;
+ int good_aces = 0;
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+
+ DEBUG(10, ("smbacl_nfs42win entered"));
+
+ aclint = get_validated_aclint(acl);
+ if (aclint==NULL)
+ return False;
+
+ nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE));
+ if (nt_ace_list==NULL)
+ {
+ DEBUG(10, ("talloc error"));
+ errno = ENOMEM;
+ return False;
+ }
+ memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE));
+
+ for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
+ SEC_ACCESS mask;
+ DOM_SID sid;
+ SMB_ACE4PROP_T *ace = &aceint->prop;
+
+ DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, "
+ "who: %d\n", aceint->magic, ace->aceType, ace->flags,
+ ace->aceFlags, ace->aceMask, ace->who.id));
+
+ SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC);
+
+ if (ace->flags & SMB_ACE4_ID_SPECIAL) {
+ switch (ace->who.special_id) {
+ case SMB_ACE4_WHO_OWNER:
+ sid_copy(&sid, psid_owner);
+ break;
+ case SMB_ACE4_WHO_GROUP:
+ sid_copy(&sid, psid_group);
+ break;
+ case SMB_ACE4_WHO_EVERYONE:
+ sid_copy(&sid, &global_sid_World);
+ break;
+ default:
+ DEBUG(8, ("invalid special who id %d "
+ "ignored\n", ace->who.special_id));
+ }
+ } else {
+ if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
+ gid_to_sid(&sid, ace->who.gid);
+ } else {
+ uid_to_sid(&sid, ace->who.uid);
+ }
+ }
+ DEBUG(10, ("mapped %d to %s\n", ace->who.id,
+ sid_string_static(&sid)));
+
+ init_sec_access(&mask, ace->aceMask);
+ init_sec_ace(&nt_ace_list[good_aces++], &sid,
+ ace->aceType, mask,
+ ace->aceFlags & 0xf);
+ }
+
+ *ppnt_ace_list = nt_ace_list;
+ *pgood_aces = good_aces;
+
+ return True;
+}
+
+size_t smb_get_nt_acl_nfs4(files_struct *fsp,
+ uint32 security_info,
+ SEC_DESC **ppdesc, SMB4ACL_T *acl)
+{
+ int good_aces = 0;
+ SMB_STRUCT_STAT sbuf;
+ DOM_SID sid_owner, sid_group;
+ size_t sd_size = 0;
+ SEC_ACE *nt_ace_list = NULL;
+ SEC_ACL *psa = NULL;
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+
+ DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name));
+
+ if (acl==NULL || smb_get_naces(acl)==0)
+ return 0; /* special because we shouldn't alloc 0 for win */
+
+ if (smbacl4_GetFileOwner(fsp, &sbuf))
+ return 0;
+
+ uid_to_sid(&sid_owner, sbuf.st_uid);
+ gid_to_sid(&sid_group, sbuf.st_gid);
+
+ if (smbacl4_nfs42win(acl,
+ &sid_owner,
+ &sid_group,
+ &nt_ace_list,
+ &good_aces
+ )==False) {
+ DEBUG(8,("smbacl4_nfs42win failed\n"));
+ return 0;
+ }
+
+ psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION,
+ good_aces, nt_ace_list);
+ if (psa == NULL) {
+ DEBUG(2,("make_sec_acl failed\n"));
+ return 0;
+ }
+
+ DEBUG(10,("after make sec_acl\n"));
+ *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION,
+ SEC_DESC_SELF_RELATIVE,
+ (security_info & OWNER_SECURITY_INFORMATION)
+ ? &sid_owner : NULL,
+ (security_info & GROUP_SECURITY_INFORMATION)
+ ? &sid_group : NULL,
+ NULL, psa, &sd_size);
+ if (*ppdesc==NULL) {
+ DEBUG(2,("make_sec_desc failed\n"));
+ return 0;
+ }
+
+ DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size));
+ return sd_size;
+}
+
+enum smbacl4_mode_enum {e_simple=0, e_special=1};
+enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3};
+
+typedef struct _smbacl4_vfs_params {
+ enum smbacl4_mode_enum mode;
+ BOOL do_chown;
+ enum smbacl4_acedup_enum acedup;
+} smbacl4_vfs_params;
+
+/*
+ * Gather special parameters for NFS4 ACL handling
+ */
+static int smbacl4_get_vfs_params(
+ const char *type_name,
+ files_struct *fsp,
+ smbacl4_vfs_params *params
+)
+{
+ static const struct enum_list enum_smbacl4_modes[] = {
+ { e_simple, "simple" },
+ { e_special, "special" }
+ };
+ static const struct enum_list enum_smbacl4_acedups[] = {
+ { e_dontcare, "dontcare" },
+ { e_reject, "reject" },
+ { e_ignore, "ignore" },
+ { e_merge, "merge" },
+ };
+
+ memset(params, 0, sizeof(smbacl4_vfs_params));
+ params->mode = (enum smbacl4_mode_enum)lp_parm_enum(
+ SNUM(fsp->conn), type_name,
+ "mode", enum_smbacl4_modes, e_simple);
+ params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name,
+ "chown", True);
+ params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum(
+ SNUM(fsp->conn), type_name,
+ "acedup", enum_smbacl4_acedups, e_dontcare);
+
+ DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
+ enum_smbacl4_modes[params->mode].name,
+ params->do_chown ? "true" : "false",
+ enum_smbacl4_acedups[params->acedup].name));
+
+ return 0;
+}
+
+static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl)
+{
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACE4_INT_T *aceint;
+
+ DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces));
+
+ for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
+ SMB_ACE4PROP_T *ace = &aceint->prop;
+
+ DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n",
+ ace->aceType,
+ ace->aceFlags, ace->flags,
+ ace->aceMask,
+ ace->who.id));
+ }
+}
+
+/*
+ * Find 2 NFS4 who-special ACE property (non-copy!!!)
+ * match nonzero if "special" and who is equal
+ * return ace if found matching; otherwise NULL
+ */
+static SMB_ACE4PROP_T *smbacl4_find_equal_special(
+ SMB4ACL_T *acl,
+ SMB_ACE4PROP_T *aceNew)
+{
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACE4_INT_T *aceint;
+
+ for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
+ SMB_ACE4PROP_T *ace = &aceint->prop;
+
+ if (ace->flags == aceNew->flags &&
+ ace->aceType==aceNew->aceType &&
+ (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)==
+ (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)
+ ) {
+ /* keep type safety; e.g. gid is an u.short */
+ if (ace->flags & SMB_ACE4_ID_SPECIAL)
+ {
+ if (ace->who.special_id==aceNew->who.special_id)
+ return ace;
+ } else {
+ if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
+ {
+ if (ace->who.gid==aceNew->who.gid)
+ return ace;
+ } else {
+ if (ace->who.uid==aceNew->who.uid)
+ return ace;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int smbacl4_fill_ace4(
+ TALLOC_CTX *mem_ctx,
+ smbacl4_vfs_params *params,
+ uid_t ownerUID,
+ gid_t ownerGID,
+ SEC_ACE *ace_nt, /* input */
+ SMB_ACE4PROP_T *ace_v4 /* output */
+)
+{
+ const char *dom, *name;
+ enum lsa_SidType type;
+ uid_t uid;
+ gid_t gid;
+
+ DEBUG(10, ("got ace for %s\n",
+ sid_string_static(&ace_nt->trustee)));
+
+ memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T));
+ ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */
+ ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT;
+ ace_v4->aceMask = ace_nt->access_mask &
+ (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS);
+
+ if (ace_v4->aceFlags!=ace_nt->flags)
+ DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
+ ace_v4->aceFlags, ace_nt->flags));
+
+ if (ace_v4->aceMask!=ace_nt->access_mask)
+ DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
+ ace_v4->aceMask, ace_nt->access_mask));
+
+ if (sid_equal(&ace_nt->trustee, &global_sid_World)) {
+ ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
+ ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+ } else {
+ if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) {
+ DEBUG(8, ("Could not find %s' type\n",
+ sid_string_static(&ace_nt->trustee)));
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (type == SID_NAME_USER) {
+ if (!sid_to_uid(&ace_nt->trustee, &uid)) {
+ DEBUG(2, ("Could not convert %s to uid\n",
+ sid_string_static(&ace_nt->trustee)));
+ return -1;
+ }
+
+ if (params->mode==e_special && uid==ownerUID) {
+ ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+ ace_v4->who.special_id = SMB_ACE4_WHO_OWNER;
+ } else {
+ ace_v4->who.uid = uid;
+ }
+ } else { /* else group? - TODO check it... */
+ if (!sid_to_gid(&ace_nt->trustee, &gid)) {
+ DEBUG(2, ("Could not convert %s to gid\n",
+ sid_string_static(&ace_nt->trustee)));
+ return -1;
+ }
+ ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
+
+ if (params->mode==e_special && gid==ownerGID) {
+ ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
+ ace_v4->who.special_id = SMB_ACE4_WHO_GROUP;
+ } else {
+ ace_v4->who.gid = gid;
+ }
+ }
+ }
+
+ return 0; /* OK */
+}
+
+static int smbacl4_MergeIgnoreReject(
+ enum smbacl4_acedup_enum acedup,
+ SMB4ACL_T *acl, /* may modify it */
+ SMB_ACE4PROP_T *ace, /* the "new" ACE */
+ BOOL *paddNewACE,
+ int i
+)
+{
+ int result = 0;
+ SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace);
+ if (ace4found)
+ {
+ switch(acedup)
+ {
+ case e_merge: /* "merge" flags */
+ *paddNewACE = False;
+ ace4found->aceFlags |= ace->aceFlags;
+ ace4found->aceMask |= ace->aceMask;
+ break;
+ case e_ignore: /* leave out this record */
+ *paddNewACE = False;
+ break;
+ case e_reject: /* do an error */
+ DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i));
+ errno = EINVAL; /* SHOULD be set on any _real_ error */
+ result = -1;
+ break;
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+static SMB4ACL_T *smbacl4_win2nfs4(
+ SEC_ACL *dacl,
+ smbacl4_vfs_params *pparams,
+ uid_t ownerUID,
+ gid_t ownerGID
+)
+{
+ SMB4ACL_T *acl;
+ uint32 i;
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+
+ DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
+
+ acl = smb_create_smb4acl();
+ if (acl==NULL)
+ return NULL;
+
+ for(i=0; i<dacl->num_aces; i++) {
+ SMB_ACE4PROP_T ace_v4;
+ BOOL addNewACE = True;
+
+ if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID,
+ dacl->aces + i, &ace_v4))
+ return NULL;
+
+ if (pparams->acedup!=e_dontcare) {
+ if (smbacl4_MergeIgnoreReject(pparams->acedup, acl,
+ &ace_v4, &addNewACE, i))
+ return NULL;
+ }
+
+ if (addNewACE)
+ smb_add_ace4(acl, &ace_v4);
+ }
+
+ return acl;
+}
+
+BOOL smb_set_nt_acl_nfs4(files_struct *fsp,
+ uint32 security_info_sent,
+ SEC_DESC *psd,
+ set_nfs4acl_native_fn_t set_nfs4_native)
+{
+ smbacl4_vfs_params params;
+ SMB4ACL_T *acl = NULL;
+ BOOL result;
+
+ SMB_STRUCT_STAT sbuf;
+ BOOL need_chown = False;
+ uid_t newUID = (uid_t)-1;
+ gid_t newGID = (gid_t)-1;
+
+ DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name));
+
+ if ((security_info_sent & (DACL_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0)
+ {
+ DEBUG(9, ("security_info_sent (0x%x) ignored\n",
+ security_info_sent));
+ return True; /* won't show error - later to be refined... */
+ }
+
+ /* Special behaviours */
+ if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, &params))
+ return False;
+
+ if (smbacl4_GetFileOwner(fsp, &sbuf))
+ return False;
+
+ /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
+ if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd))
+ {
+ DEBUG(8, ("unpack_nt_owners failed"));
+ return False;
+ }
+ if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
+ ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
+ need_chown = True;
+ }
+ if (need_chown) {
+ if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
+ if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+ DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
+ return False;
+ }
+ DEBUG(10,("chown %s, %u, %u succeeded.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ if (smbacl4_GetFileOwner(fsp, &sbuf))
+ return False;
+ need_chown = False;
+ } else { /* chown is needed, but _after_ changing acl */
+ sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
+ sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
+ }
+ }
+
+ if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL)
+ {
+ acl = smbacl4_win2nfs4(psd->dacl, &params, sbuf.st_uid, sbuf.st_gid);
+ if (!acl)
+ return False;
+
+ smbacl4_dump_nfs4acl(10, acl);
+
+ result = set_nfs4_native(fsp, acl);
+ if (result!=True)
+ {
+ DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno)));
+ return False;
+ }
+ } else
+ DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent));
+
+ /* Any chown pending? */
+ if (need_chown) {
+ DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+ DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID,
+ strerror(errno)));
+ return False;
+ }
+ DEBUG(10,("chown#2 %s, %u, %u succeeded.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ }
+
+ DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
+ return True;
+}
diff --git a/source/modules/nfs4_acls.h b/source/modules/nfs4_acls.h
new file mode 100644
index 00000000000..469a50af56a
--- /dev/null
+++ b/source/modules/nfs4_acls.h
@@ -0,0 +1,146 @@
+/*
+ * NFS4 ACL handling
+ *
+ * Copyright (C) Jim McDonough, 2006
+ * Reused & renamed some parts of AIX 5.3 sys/acl.h structures
+ *
+ * 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 __NFS4_ACLS_H__
+#define __NFS4_ACLS_H__
+
+#define SMB_ACLTYPE_NONE 0
+#define SMB_ACLTYPE_UNKNOWN 1
+#define SMB_ACLTYPE_POSIX 2
+#define SMB_ACLTYPE_NFS4 4
+
+/*
+ * Following union captures the identity as
+ * used in the NFS4 ACL structures.
+ */
+typedef union _SMB_NFS4_ACEWHOID_T {
+ uid_t uid; /* User id */
+ gid_t gid; /* Group id */
+ uint32 special_id; /* Identifies special identities in NFS4 */
+
+#define SMB_ACE4_WHO_OWNER 0x00000001 /*The owner of the file. */
+#define SMB_ACE4_WHO_GROUP 0x00000002 /*The group associated with the file. */
+#define SMB_ACE4_WHO_EVERYONE 0x00000003 /*The world. */
+#define SMB_ACE4_WHO_INTERACTIVE 0x00000004 /*Accessed from an interactive terminal. */
+#define SMB_ACE4_WHO_NETWORK 0x00000005 /*Accessed via the network. */
+#define SMB_ACE4_WHO_DIALUP 0x00000006 /*Accessed as a dialup user to the server. */
+#define SMB_ACE4_WHO_BATCH 0x00000007 /*Accessed from a batch job. */
+#define SMB_ACE4_WHO_ANONYMOUS 0x00000008 /*Accessed without any authentication. */
+#define SMB_ACE4_WHO_AUTHENTICATED 0x00000009 /*Any authenticated user (opposite of ANONYMOUS) */
+#define SMB_ACE4_WHO_SERVICE 0x0000000A /*Access from a system service. */
+#define SMB_ACE4_WHO_MAX SMB_ACE4_WHO_SERVICE /* largest valid ACE4_WHO */
+ uint32 id;
+} SMB_NFS4_ACEWHOID_T;
+
+typedef struct _SMB_ACE4PROP_T {
+ uint32 flags; /* Bit mask defining details of ACE */
+/*The following are constants for flags field */
+/* #define SMB_ACE4_ID_NOT_VALID 0x00000001 - from aix/jfs2 */
+#define SMB_ACE4_ID_SPECIAL 0x00000002
+
+ SMB_NFS4_ACEWHOID_T who; /* Identifies to whom this ACE applies */
+
+ /* The following part of ACE has the same layout as NFSv4 wire format. */
+
+ uint32 aceType; /* Type of ACE PERMIT/ALLOW etc*/
+/*The constants used for the type field (acetype4) are as follows: */
+#define SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
+#define SMB_ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
+#define SMB_ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
+#define SMB_ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
+#define SMB_ACE4_MAX_TYPE ACE4_SYSTEM_ALARM_ACE_TYPE /* largest valid ACE4_TYPE */
+
+ uint32 aceFlags; /* Controls Inheritance and such */
+/*The bitmask constants used for the flag field are as follows: */
+#define SMB_ACE4_FILE_INHERIT_ACE 0x00000001
+#define SMB_ACE4_DIRECTORY_INHERIT_ACE 0x00000002
+#define SMB_ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
+#define SMB_ACE4_INHERIT_ONLY_ACE 0x00000008
+#define SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
+#define SMB_ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
+#define SMB_ACE4_IDENTIFIER_GROUP 0x00000040
+#define SMB_ACE4_ALL_FLAGS ( SMB_ACE4_FILE_INHERIT_ACE | SMB_ACE4_DIRECTORY_INHERIT_ACE \
+| SMB_ACE4_NO_PROPAGATE_INHERIT_ACE | SMB_ACE4_INHERIT_ONLY_ACE | SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG \
+| SMB_ACE4_FAILED_ACCESS_ACE_FLAG | SMB_ACE4_IDENTIFIER_GROUP )
+
+ uint32 aceMask; /* Access rights */
+/*The bitmask constants used for the access mask field are as follows: */
+#define SMB_ACE4_READ_DATA 0x00000001
+#define SMB_ACE4_LIST_DIRECTORY 0x00000001
+#define SMB_ACE4_WRITE_DATA 0x00000002
+#define SMB_ACE4_ADD_FILE 0x00000002
+#define SMB_ACE4_APPEND_DATA 0x00000004
+#define SMB_ACE4_ADD_SUBDIRECTORY 0x00000004
+#define SMB_ACE4_READ_NAMED_ATTRS 0x00000008
+#define SMB_ACE4_WRITE_NAMED_ATTRS 0x00000010
+#define SMB_ACE4_EXECUTE 0x00000020
+#define SMB_ACE4_DELETE_CHILD 0x00000040
+#define SMB_ACE4_READ_ATTRIBUTES 0x00000080
+#define SMB_ACE4_WRITE_ATTRIBUTES 0x00000100
+#define SMB_ACE4_DELETE 0x00010000
+#define SMB_ACE4_READ_ACL 0x00020000
+#define SMB_ACE4_WRITE_ACL 0x00040000
+#define SMB_ACE4_WRITE_OWNER 0x00080000
+#define SMB_ACE4_SYNCHRONIZE 0x00100000
+#define SMB_ACE4_ALL_MASKS ( SMB_ACE4_READ_DATA | SMB_ACE4_LIST_DIRECTORY \
+| SMB_ACE4_WRITE_DATA | SMB_ACE4_ADD_FILE | SMB_ACE4_APPEND_DATA | SMB_ACE4_ADD_SUBDIRECTORY \
+| SMB_ACE4_READ_NAMED_ATTRS | SMB_ACE4_WRITE_NAMED_ATTRS | SMB_ACE4_EXECUTE | SMB_ACE4_DELETE_CHILD \
+| SMB_ACE4_READ_ATTRIBUTES | SMB_ACE4_WRITE_ATTRIBUTES | SMB_ACE4_DELETE | SMB_ACE4_READ_ACL \
+| SMB_ACE4_WRITE_ACL | SMB_ACE4_WRITE_OWNER | SMB_ACE4_SYNCHRONIZE )
+} SMB_ACE4PROP_T;
+
+/*
+ * Never allocate these structures on your own
+ * use create_smb4acl instead
+ */
+typedef struct _SMB4ACL_T {char dontuse;} SMB4ACL_T;
+typedef struct _SMB4ACE_T {char dontuse;} SMB4ACE_T;
+
+SMB4ACL_T *smb_create_smb4acl(void);
+
+/* prop's contents are copied */
+/* it doesn't change the order, appends */
+SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop);
+
+SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace);
+
+/* Returns NULL if none - or error */
+SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl);
+
+/* Returns NULL in the end - or error */
+SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace);
+
+uint32 smb_get_naces(SMB4ACL_T *acl);
+
+size_t smb_get_nt_acl_nfs4(files_struct *fsp,
+ uint32 security_info,
+ SEC_DESC **ppdesc, SMB4ACL_T *acl);
+
+/* Callback function needed to set the native acl
+ * when applicable */
+typedef BOOL (*set_nfs4acl_native_fn_t)(files_struct *, SMB4ACL_T *);
+
+BOOL smb_set_nt_acl_nfs4(files_struct *fsp,
+ uint32 security_info_sent,
+ SEC_DESC *psd,
+ set_nfs4acl_native_fn_t set_nfs4_native);
+
+#endif /* __NFS4_ACLS_H__ */
diff --git a/source/modules/vfs_afsacl.c b/source/modules/vfs_afsacl.c
index 90a3045126d..43fa537d734 100644
--- a/source/modules/vfs_afsacl.c
+++ b/source/modules/vfs_afsacl.c
@@ -48,7 +48,7 @@ struct afs_ace {
BOOL positive;
char *name;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
uint32 rights;
struct afs_ace *next;
};
@@ -110,7 +110,7 @@ static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx,
const char *name, uint32 rights)
{
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
struct afs_ace *result;
if (strcmp(name, "system:administrators") == 0) {
@@ -589,7 +589,7 @@ static uint32 nt_to_afs_file_rights(const char *filename, const SEC_ACE *ace)
static size_t afs_to_nt_acl(struct afs_acl *afs_acl,
struct files_struct *fsp,
uint32 security_info,
- struct security_descriptor_info **ppdesc)
+ struct security_descriptor **ppdesc)
{
SEC_ACE *nt_ace_list;
DOM_SID owner_sid, group_sid;
@@ -691,7 +691,7 @@ static BOOL mappable_sid(const DOM_SID *sid)
static BOOL nt_to_afs_acl(const char *filename,
uint32 security_info_sent,
- struct security_descriptor_info *psd,
+ struct security_descriptor *psd,
uint32 (*nt_to_afs_rights)(const char *filename,
const SEC_ACE *ace),
struct afs_acl *afs_acl)
@@ -713,7 +713,7 @@ static BOOL nt_to_afs_acl(const char *filename,
for (i = 0; i < dacl->num_aces; i++) {
SEC_ACE *ace = &(dacl->ace[i]);
const char *dom_name, *name;
- enum SID_NAME_USE name_type;
+ enum lsa_SidType name_type;
char *p;
if (ace->type != SEC_ACE_TYPE_ACCESS_ALLOWED) {
@@ -827,7 +827,7 @@ static BOOL afs_get_afs_acl(char *filename, struct afs_acl *acl)
}
static size_t afs_get_nt_acl(struct files_struct *fsp, uint32 security_info,
- struct security_descriptor_info **ppdesc)
+ struct security_descriptor **ppdesc)
{
struct afs_acl acl;
size_t sd_size;
@@ -881,7 +881,7 @@ static void merge_unknown_aces(struct afs_acl *src, struct afs_acl *dst)
static BOOL afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info_sent,
- struct security_descriptor_info *psd)
+ struct security_descriptor *psd)
{
struct afs_acl old_afs_acl, new_afs_acl;
struct afs_acl dir_acl, file_acl;
@@ -982,14 +982,14 @@ static BOOL afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
static size_t afsacl_fget_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
int fd, uint32 security_info,
- struct security_descriptor_info **ppdesc)
+ struct security_descriptor **ppdesc)
{
return afs_get_nt_acl(fsp, security_info, ppdesc);
}
static size_t afsacl_get_nt_acl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
const char *name, uint32 security_info,
- struct security_descriptor_info **ppdesc)
+ struct security_descriptor **ppdesc)
{
return afs_get_nt_acl(fsp, security_info, ppdesc);
}
@@ -1011,7 +1011,6 @@ BOOL afsacl_set_nt_acl(vfs_handle_struct *handle,
}
static int afsacl_connect(vfs_handle_struct *handle,
- connection_struct *conn,
const char *service,
const char *user)
{
@@ -1022,7 +1021,7 @@ static int afsacl_connect(vfs_handle_struct *handle,
if (spc != NULL)
space_replacement = spc[0];
- return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
}
/* VFS operations structure */
@@ -1041,6 +1040,7 @@ static vfs_op_tuple afsacl_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_afsacl_init(void);
NTSTATUS vfs_afsacl_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "afsacl",
diff --git a/source/modules/vfs_aixacl.c b/source/modules/vfs_aixacl.c
new file mode 100644
index 00000000000..20c469e36c0
--- /dev/null
+++ b/source/modules/vfs_aixacl.c
@@ -0,0 +1,216 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set posix acls
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
+
+ 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"
+
+extern SMB_ACL_T aixacl_to_smbacl( struct acl *file_acl);
+extern struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
+
+SMB_ACL_T aixacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ struct acl *file_acl = (struct acl *)NULL;
+ struct smb_acl_t *result = (struct smb_acl_t *)NULL;
+
+ int rc = 0;
+ uid_t user_id;
+
+ /* AIX has no DEFAULT */
+ if ( type == SMB_ACL_TYPE_DEFAULT )
+ return NULL;
+
+ /* Get the acl using statacl */
+
+ DEBUG(10,("Entering AIX sys_acl_get_file\n"));
+ DEBUG(10,("path_p is %s\n",path_p));
+
+ file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
+
+ if(file_acl == NULL) {
+ errno=ENOMEM;
+ DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
+ return(NULL);
+ }
+
+ memset(file_acl,0,BUFSIZ);
+
+ rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
+ if( (rc == -1) && (errno == ENOSPC)) {
+ struct acl *new_acl = SMB_MALLOC(file_acl->acl_len + sizeof(struct acl));
+ if( new_acl == NULL) {
+ SAFE_FREE(file_acl);
+ errno = ENOMEM;
+ return NULL;
+ }
+ file_acl = new_acl;
+ rc = statacl((char *)path_p,0,file_acl,file_acl->acl_len+sizeof(struct acl));
+ if( rc == -1) {
+ DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
+ SAFE_FREE(file_acl);
+ return(NULL);
+ }
+ }
+
+ DEBUG(10,("Got facl and returned it\n"));
+
+
+ result = aixacl_to_smbacl(file_acl);
+ SAFE_FREE(file_acl);
+ return result;
+
+ /*errno = ENOTSUP;
+ return NULL;*/
+}
+
+SMB_ACL_T aixacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+
+ struct acl *file_acl = (struct acl *)NULL;
+ struct smb_acl_t *result = (struct smb_acl_t *)NULL;
+
+ int rc = 0;
+ uid_t user_id;
+
+ /* Get the acl using fstatacl */
+
+ DEBUG(10,("Entering AIX sys_acl_get_fd\n"));
+ DEBUG(10,("fd is %d\n",fd));
+ file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
+
+ if(file_acl == NULL) {
+ errno=ENOMEM;
+ DEBUG(0,("Error in AIX sys_acl_get_fd is %d\n",errno));
+ return(NULL);
+ }
+
+ memset(file_acl,0,BUFSIZ);
+
+ rc = fstatacl(fd,0,file_acl,BUFSIZ);
+ if( (rc == -1) && (errno == ENOSPC)) {
+ struct acl *new_acl = SMB_MALLOC(file_acl->acl_len + sizeof(struct acl));
+ if( new_acl == NULL) {
+ SAFE_FREE(file_acl);
+ errno = ENOMEM;
+ return NULL;
+ }
+ file_acl = new_acl;
+ rc = fstatacl(fd,0,file_acl,file_acl->acl_len + sizeof(struct acl));
+ if( rc == -1) {
+ DEBUG(0,("fstatacl returned %d with errno %d\n",rc,errno));
+ SAFE_FREE(file_acl);
+ return(NULL);
+ }
+ }
+
+ DEBUG(10,("Got facl and returned it\n"));
+
+ result = aixacl_to_smbacl(file_acl);
+ SAFE_FREE(file_acl);
+ return result;
+
+ /*errno = ENOTSUP;
+ return NULL;*/
+}
+
+int aixacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ struct acl *file_acl = NULL;
+ uint rc;
+
+ file_acl = aixacl_smb_to_aixacl(type, theacl);
+ if (!file_acl)
+ return -1;
+
+ rc = chacl((char *)name,file_acl,file_acl->acl_len);
+ DEBUG(10,("errno is %d\n",errno));
+ DEBUG(10,("return code is %d\n",rc));
+ SAFE_FREE(file_acl);
+ DEBUG(10,("Exiting the aixacl_sys_acl_set_file\n"));
+
+ return rc;
+}
+
+int aixacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ struct acl *file_acl = NULL;
+ uint rc;
+
+ file_acl = aixacl_smb_to_aixacl(SMB_ACL_TYPE_ACCESS, theacl);
+ if (!file_acl)
+ return -1;
+
+ rc = fchacl(fd,file_acl,file_acl->acl_len);
+ DEBUG(10,("errno is %d\n",errno));
+ DEBUG(10,("return code is %d\n",rc));
+ SAFE_FREE(file_acl);
+ DEBUG(10,("Exiting aixacl_sys_acl_set_fd\n"));
+
+ return rc;
+}
+
+int aixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ return 0; /* otherwise you can't set acl at upper level */
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple aixacl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(aixacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_aixacl_init(void);
+NTSTATUS vfs_aixacl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "aixacl",
+ aixacl_op_tuples);
+}
diff --git a/source/modules/vfs_aixacl2.c b/source/modules/vfs_aixacl2.c
new file mode 100644
index 00000000000..62a517a6e08
--- /dev/null
+++ b/source/modules/vfs_aixacl2.c
@@ -0,0 +1,538 @@
+/*
+ * Convert JFS2 NFS4/AIXC acls to NT acls and vice versa.
+ *
+ * Copyright (C) Volker Lendecke, 2006
+ *
+ * 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 "nfs4_acls.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+#define AIXACL2_MODULE_NAME "aixacl2"
+
+extern struct current_user current_user;
+extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid);
+extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp,
+ uint32 security_info_sent, SEC_DESC *psd);
+
+extern SMB_ACL_T aixacl_to_smbacl( struct acl *file_acl);
+extern struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
+
+typedef union aixjfs2_acl_t {
+ nfs4_acl_int_t jfs2_acl[1];
+ aixc_acl_t aixc_acl[1];
+}AIXJFS2_ACL_T;
+
+static int32_t aixacl2_getlen(AIXJFS2_ACL_T *acl, acl_type_t *type)
+{
+ int32_t len;
+
+ if(type->u64 == ACL_NFS4) {
+ len = acl->jfs2_acl[0].aclLength;
+ }
+ else {
+ if(type->u64 == ACL_AIXC) {
+ len = acl->aixc_acl[0].acl_len;
+ } else {
+ DEBUG(0,("aixacl2_getlen:unknown type:%d\n",type->u64));
+ return False;
+ }
+ }
+ DEBUG(10,("aixacl2_getlen:%d\n",len));
+ return len;
+}
+
+static AIXJFS2_ACL_T *aixjfs2_getacl_alloc(const char *fname, acl_type_t *type)
+{
+ AIXJFS2_ACL_T *acl;
+ size_t len = 200;
+ mode_t mode;
+ int ret;
+ uint64_t ctl_flag=0;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = main_loop_talloc_get();
+ acl = (AIXJFS2_ACL_T *)talloc_size(mem_ctx, len);
+ if (acl == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ if(type->u64 == ACL_ANY) {
+ ctl_flag = ctl_flag | GET_ACLINFO_ONLY;
+ }
+
+ ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
+ if ((ret != 0) && (errno == ENOSPC)) {
+ len = aixacl2_getlen(acl, type) + sizeof(AIXJFS2_ACL_T);
+ DEBUG(10,("aixjfs2_getacl_alloc - acl_len:%d\n",len));
+
+ acl = (AIXJFS2_ACL_T *)talloc_size(mem_ctx, len);
+ if (acl == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
+ }
+ if (ret != 0) {
+ DEBUG(8, ("aclx_get failed with %s\n", strerror(errno)));
+ return NULL;
+ }
+
+ return acl;
+}
+
+static BOOL aixjfs2_get_nfs4_acl(files_struct *fsp,
+ SMB4ACL_T **ppacl, BOOL *pretryPosix)
+{
+ int32_t i;
+
+ AIXJFS2_ACL_T *pacl = NULL;
+ nfs4_acl_int_t *jfs2_acl = NULL;
+ nfs4_ace_int_t *jfs2_ace = NULL;
+ acl_type_t type;
+
+ DEBUG(10,("jfs2 get_nt_acl invoked for %s\n", fsp->fsp_name));
+
+ memset(&type, 0, sizeof(acl_type_t));
+ type.u64 = ACL_NFS4;
+
+ pacl = aixjfs2_getacl_alloc(fsp->fsp_name, &type);
+ if (pacl == NULL) {
+ DEBUG(9, ("aixjfs2_getacl_alloc failed for %s with %s\n",
+ fsp->fsp_name, strerror(errno)));
+ if (errno==ENOSYS)
+ *pretryPosix = True;
+ return False;
+ }
+
+ jfs2_acl = &pacl->jfs2_acl[0];
+ DEBUG(10, ("len: %d, version: %d, nace: %d, type: 0x%x\n",
+ jfs2_acl->aclLength, jfs2_acl->aclVersion, jfs2_acl->aclEntryN, type.u64));
+
+ *ppacl = smb_create_smb4acl();
+ if (*ppacl==NULL)
+ return False;
+
+ jfs2_ace = &jfs2_acl->aclEntry[0];
+ for (i=0; i<jfs2_acl->aclEntryN; i++) {
+ SMB_ACE4PROP_T aceprop;
+
+ DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
+ "who: %d, aclLen: %d\n", jfs2_ace->aceType, jfs2_ace->flags,
+ jfs2_ace->aceFlags, jfs2_ace->aceMask, jfs2_ace->aceWho.id, jfs2_ace->entryLen));
+
+ aceprop.aceType = jfs2_ace->aceType;
+ aceprop.aceFlags = jfs2_ace->aceFlags;
+ aceprop.aceMask = jfs2_ace->aceMask;
+ aceprop.flags = (jfs2_ace->flags&ACE4_ID_SPECIAL) ? SMB_ACE4_ID_SPECIAL : 0;
+
+ /* don't care it's real content is only 16 or 32 bit */
+ aceprop.who.id = jfs2_ace->aceWho.id;
+
+ if (smb_add_ace4(*ppacl, &aceprop)==NULL)
+ return False;
+
+ /* iterate to the next jfs2 ace */
+ jfs2_ace = (nfs4_ace_int_t *)(((char *)jfs2_ace) + jfs2_ace->entryLen);
+ }
+
+ DEBUG(10,("jfs2 get_nt_acl finished successfully\n"));
+
+ return True;
+}
+
+static size_t aixjfs2_get_nt_acl_common(files_struct *fsp,
+ uint32 security_info, SEC_DESC **ppdesc)
+{
+ SMB4ACL_T *pacl = NULL;
+ BOOL result;
+ BOOL retryPosix = False;
+
+ *ppdesc = NULL;
+ result = aixjfs2_get_nfs4_acl(fsp, &pacl, &retryPosix);
+ if (retryPosix)
+ {
+ DEBUG(10, ("retrying with posix acl...\n"));
+ return get_nt_acl(fsp, security_info, ppdesc);
+ }
+ if (result==False)
+ return 0;
+
+ return smb_get_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
+}
+
+size_t aixjfs2_fget_nt_acl(vfs_handle_struct *handle,
+ files_struct *fsp, int fd, uint32 security_info,
+ SEC_DESC **ppdesc)
+{
+ return aixjfs2_get_nt_acl_common(fsp, security_info, ppdesc);
+}
+
+size_t aixjfs2_get_nt_acl(vfs_handle_struct *handle,
+ files_struct *fsp, const char *name,
+ uint32 security_info, SEC_DESC **ppdesc)
+{
+ return aixjfs2_get_nt_acl_common(fsp, security_info, ppdesc);
+}
+
+static SMB_ACL_T aixjfs2_get_posix_acl(const char *path, acl_type_t type)
+{
+ aixc_acl_t *pacl;
+ AIXJFS2_ACL_T *acl;
+ SMB_ACL_T result = NULL;
+ int ret;
+
+ acl = aixjfs2_getacl_alloc(path, &type);
+
+ if (acl == NULL) {
+ DEBUG(10, ("aixjfs2_getacl failed for %s with %s\n",
+ path, strerror(errno)));
+ if (errno == 0) {
+ errno = EINVAL;
+ }
+ goto done;
+ }
+
+ pacl = &acl->aixc_acl[0];
+ DEBUG(10, ("len: %d, mode: %d\n",
+ pacl->acl_len, pacl->acl_mode));
+
+ result = aixacl_to_smbacl(pacl);
+ if (result == NULL) {
+ goto done;
+ }
+
+ done:
+ if (errno != 0) {
+ SAFE_FREE(result);
+ }
+ return result;
+}
+
+SMB_ACL_T aixjfs2_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ acl_type_t aixjfs2_type;
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ aixjfs2_type.u64 = ACL_AIXC;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ DEBUG(0, ("Got AIX JFS2 unsupported type: %d\n", type));
+ return NULL;
+ default:
+ DEBUG(0, ("Got invalid type: %d\n", type));
+ smb_panic("exiting");
+ }
+
+ return aixjfs2_get_posix_acl(path_p, aixjfs2_type);
+}
+
+SMB_ACL_T aixjfs2_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ acl_type_t aixjfs2_type;
+ aixjfs2_type.u64 = ACL_AIXC;
+
+ return aixjfs2_get_posix_acl(fsp->fsp_name, aixjfs2_type);
+}
+
+/*
+ * Test whether we have that aclType support on the given path
+ */
+static int aixjfs2_query_acl_support(
+ char *filepath,
+ uint64_t aclType,
+ acl_type_t *pacl_type_info
+)
+{
+ acl_types_list_t acl_type_list;
+ size_t acl_type_list_len = sizeof(acl_types_list_t);
+ uint32_t i;
+
+ memset(&acl_type_list, 0, sizeof(acl_type_list));
+
+ if (aclx_gettypes(filepath, &acl_type_list, &acl_type_list_len)) {
+ DEBUG(2, ("aclx_gettypes failed with error %s for %s\n",
+ strerror(errno), filepath));
+ return -1;
+ }
+
+ for(i=0; i<acl_type_list.num_entries; i++) {
+ if (acl_type_list.entries[i].u64==aclType) {
+ memcpy(pacl_type_info, acl_type_list.entries + i, sizeof(acl_type_t));
+ DEBUG(10, ("found %s ACL support for %s\n",
+ pacl_type_info->acl_type, filepath));
+ return 0;
+ }
+ }
+
+ return 1; /* haven't found that ACL type. */
+}
+
+static BOOL aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
+{
+ SMB4ACE_T *smbace;
+ TALLOC_CTX *mem_ctx;
+ nfs4_acl_int_t *jfs2acl;
+ int32_t entryLen;
+ uint32 aclLen, naces;
+ int rc;
+ acl_type_t acltype;
+
+ DEBUG(10, ("jfs2_process_smbacl invoked on %s\n", fsp->fsp_name));
+
+ /* no need to be freed which is alloced with mem_ctx */
+ mem_ctx = main_loop_talloc_get();
+
+ entryLen = sizeof(nfs4_ace_int_t);
+ if (entryLen & 0x03)
+ entryLen = entryLen + 4 - (entryLen%4);
+
+ naces = smb_get_naces(smbacl);
+ aclLen = ACL_V4_SIZ + naces * entryLen;
+ jfs2acl = (nfs4_acl_int_t *)talloc_size(mem_ctx, aclLen);
+ if (jfs2acl==NULL) {
+ DEBUG(0, ("talloc_size failed\n"));
+ errno = ENOMEM;
+ return False;
+ }
+
+ jfs2acl->aclLength = ACL_V4_SIZ;
+ jfs2acl->aclVersion = NFS4_ACL_INT_STRUCT_VERSION;
+ jfs2acl->aclEntryN = 0;
+
+ for(smbace = smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace))
+ {
+ SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
+ nfs4_ace_int_t *jfs2_ace = (nfs4_ace_int_t *)(((char *)jfs2acl) + jfs2acl->aclLength);
+
+ memset(jfs2_ace, 0, entryLen);
+ jfs2_ace->entryLen = entryLen; /* won't store textual "who" */
+ jfs2_ace->aceType = aceprop->aceType; /* only ACCES|DENY supported by jfs2 */
+ jfs2_ace->aceFlags = aceprop->aceFlags;
+ jfs2_ace->aceMask = aceprop->aceMask;
+ jfs2_ace->flags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_ID_SPECIAL : 0;
+
+ /* don't care it's real content is only 16 or 32 bit */
+ jfs2_ace->aceWho.id = aceprop->who.id;
+
+ /* iterate to the next jfs2 ace */
+ jfs2acl->aclLength += jfs2_ace->entryLen;
+ jfs2acl->aclEntryN++;
+ }
+ SMB_ASSERT(jfs2acl->aclEntryN==naces);
+
+ /* Don't query it (again) */
+ memset(&acltype, 0, sizeof(acl_type_t));
+ acltype.u64 = ACL_NFS4;
+
+ /* won't set S_ISUID - the only one JFS2/NFS4 accepts */
+ rc = aclx_put(
+ fsp->fsp_name,
+ SET_ACL, /* set only the ACL, not mode bits */
+ acltype, /* not a pointer !!! */
+ jfs2acl,
+ jfs2acl->aclLength,
+ 0 /* don't set here mode bits */
+ );
+ if (rc) {
+ DEBUG(8, ("aclx_put failed with %s\n", strerror(errno)));
+ return False;
+ }
+
+ DEBUG(10, ("jfs2_process_smbacl succeeded.\n"));
+ return True;
+}
+
+static BOOL aixjfs2_set_nt_acl_common(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
+{
+ acl_type_t acl_type_info;
+ BOOL result = False;
+ int rc;
+
+ rc = aixjfs2_query_acl_support(
+ fsp->fsp_name,
+ ACL_NFS4,
+ &acl_type_info);
+
+ if (rc==0)
+ {
+ result = smb_set_nt_acl_nfs4(
+ fsp, security_info_sent, psd,
+ aixjfs2_process_smbacl);
+ } else if (rc==1) { /* assume POSIX ACL - by default... */
+ result = set_nt_acl(fsp, security_info_sent, psd);
+ } else
+ result = False; /* query failed */
+
+ return result;
+}
+
+BOOL aixjfs2_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
+{
+ return aixjfs2_set_nt_acl_common(fsp, security_info_sent, psd);
+}
+
+BOOL aixjfs2_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
+{
+ return aixjfs2_set_nt_acl_common(fsp, security_info_sent, psd);
+}
+
+int aixjfs2_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ struct acl *acl_aixc;
+ acl_type_t acl_type_info;
+ int rc;
+
+ DEBUG(10, ("aixjfs2_sys_acl_set_file invoked for %s", name));
+
+ rc = aixjfs2_query_acl_support((char *)name, ACL_AIXC, &acl_type_info);
+ if (rc) {
+ DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n"));
+ return -1;
+ }
+
+ acl_aixc = aixacl_smb_to_aixacl(type, theacl);
+ if (!acl_aixc)
+ return -1;
+
+ rc = aclx_put(
+ (char *)name,
+ SET_ACL, /* set only the ACL, not mode bits */
+ acl_type_info,
+ acl_aixc,
+ acl_aixc->acl_len,
+ 0
+ );
+ if (rc) {
+ DEBUG(2, ("aclx_put failed with %s for %s\n",
+ strerror(errno), name));
+ return -1;
+ }
+
+ return 0;
+}
+
+int aixjfs2_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ struct acl *acl_aixc;
+ acl_type_t acl_type_info;
+ int rc;
+
+ DEBUG(10, ("aixjfs2_sys_acl_set_fd invoked for %s", fsp->fsp_name));
+
+ rc = aixjfs2_query_acl_support(fsp->fsp_name, ACL_AIXC, &acl_type_info);
+ if (rc) {
+ DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n"));
+ return -1;
+ }
+
+ acl_aixc = aixacl_smb_to_aixacl(SMB_ACL_TYPE_ACCESS, theacl);
+ if (!acl_aixc)
+ return -1;
+
+ rc = aclx_fput(
+ fd,
+ SET_ACL, /* set only the ACL, not mode bits */
+ acl_type_info,
+ acl_aixc,
+ acl_aixc->acl_len,
+ 0
+ );
+ if (rc) {
+ DEBUG(2, ("aclx_fput failed with %s for %s\n",
+ strerror(errno), fsp->fsp_name));
+ return -1;
+ }
+
+ return 0;
+}
+
+int aixjfs2_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ /* Not available under AIXC ACL */
+ /* Don't report here any error otherwise */
+ /* upper layer will break the normal execution */
+ return 0;
+}
+
+
+/* VFS operations structure */
+
+static vfs_op_tuple aixjfs2_ops[] =
+{
+ {SMB_VFS_OP(aixjfs2_fget_nt_acl),
+ SMB_VFS_OP_FGET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_get_nt_acl),
+ SMB_VFS_OP_GET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_fset_nt_acl),
+ SMB_VFS_OP_FSET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_set_nt_acl),
+ SMB_VFS_OP_SET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(aixjfs2_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_aixacl2_init(void);
+NTSTATUS vfs_aixacl2_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, AIXACL2_MODULE_NAME,
+ aixjfs2_ops);
+}
diff --git a/source/modules/vfs_aixacl_util.c b/source/modules/vfs_aixacl_util.c
new file mode 100644
index 00000000000..fd7481af3ef
--- /dev/null
+++ b/source/modules/vfs_aixacl_util.c
@@ -0,0 +1,297 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set posix acls
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
+
+ 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"
+
+SMB_ACL_T aixacl_to_smbacl(struct acl *file_acl)
+{
+ struct acl_entry *acl_entry;
+ struct ace_id *idp;
+
+ struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
+ struct smb_acl_entry *ace;
+ int i;
+
+ if (result == NULL) {
+ return NULL;
+ }
+ ZERO_STRUCTP(result);
+
+ /* Point to the first acl entry in the acl */
+ acl_entry = file_acl->acl_ext;
+
+
+
+ DEBUG(10,("acl_entry is %d\n",acl_entry));
+ DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
+
+ /* Check if the extended acl bit is on. *
+ * If it isn't, do not show the *
+ * contents of the acl since AIX intends *
+ * the extended info to remain unused */
+
+ if(file_acl->acl_mode & S_IXACL){
+ /* while we are not pointing to the very end */
+ while(acl_entry < acl_last(file_acl)) {
+ /* before we malloc anything, make sure this is */
+ /* a valid acl entry and one that we want to map */
+ idp = id_nxt(acl_entry->ace_id);
+ if((acl_entry->ace_type == ACC_SPECIFY ||
+ (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
+ acl_entry = acl_nxt(acl_entry);
+ continue;
+ }
+
+ idp = acl_entry->ace_id;
+ DEBUG(10,("idp->id_data is %d\n",idp->id_data[0]));
+
+ result = SMB_REALLOC(result, sizeof(struct smb_acl_t) +
+ (sizeof(struct smb_acl_entry) *
+ (result->count+1)));
+ if (result == NULL) {
+ DEBUG(0, ("SMB_REALLOC failed\n"));
+ errno = ENOMEM;
+ return NULL;
+ }
+
+
+ DEBUG(10,("idp->id_type is %d\n",idp->id_type));
+ ace = &result->acl[result->count];
+
+ ace->a_type = idp->id_type;
+
+ switch(ace->a_type) {
+ case ACEID_USER: {
+ ace->uid = idp->id_data[0];
+ DEBUG(10,("case ACEID_USER ace->uid is %d\n",ace->uid));
+ ace->a_type = SMB_ACL_USER;
+ break;
+ }
+
+ case ACEID_GROUP: {
+ ace->gid = idp->id_data[0];
+ DEBUG(10,("case ACEID_GROUP ace->gid is %d\n",ace->gid));
+ ace->a_type = SMB_ACL_GROUP;
+ break;
+ }
+ default:
+ break;
+ }
+ /* The access in the acl entries must be left shifted by *
+ * three bites, because they will ultimately be compared *
+ * to S_IRUSR, S_IWUSR, and S_IXUSR. */
+
+ switch(acl_entry->ace_type){
+ case ACC_PERMIT:
+ case ACC_SPECIFY:
+ ace->a_perm = acl_entry->ace_access;
+ ace->a_perm <<= 6;
+ DEBUG(10,("ace->a_perm is %d\n",ace->a_perm));
+ break;
+ case ACC_DENY:
+ /* Since there is no way to return a DENY acl entry *
+ * change to PERMIT and then shift. */
+ DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
+ ace->a_perm = ~acl_entry->ace_access & 7;
+ DEBUG(10,("ace->a_perm is %d\n",ace->a_perm));
+ ace->a_perm <<= 6;
+ break;
+ default:
+ DEBUG(0, ("unknown ace->type\n"));
+ SAFE_FREE(result);
+ return(0);
+ }
+
+ result->count++;
+ ace->a_perm |= (ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0;
+ ace->a_perm |= (ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0;
+ ace->a_perm |= (ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0;
+ DEBUG(10,("ace->a_perm is %d\n",ace->a_perm));
+
+ DEBUG(10,("acl_entry = %d\n",acl_entry));
+ DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
+
+ acl_entry = acl_nxt(acl_entry);
+ }
+ } /* end of if enabled */
+
+ /* Since owner, group, other acl entries are not *
+ * part of the acl entries in an acl, they must *
+ * be dummied up to become part of the list. */
+
+ for( i = 1; i < 4; i++) {
+ DEBUG(10,("i is %d\n",i));
+
+ result = SMB_REALLOC(result, sizeof(struct smb_acl_t) +
+ (sizeof(struct smb_acl_entry) *
+ (result->count+1)));
+ if (result == NULL) {
+ DEBUG(0, ("SMB_REALLOC failed\n"));
+ errno = ENOMEM;
+ DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
+ return NULL;
+ }
+
+ ace = &result->acl[result->count];
+
+ ace->uid = 0;
+ ace->gid = 0;
+ DEBUG(10,("ace->uid = %d\n",ace->uid));
+
+ switch(i) {
+ case 2:
+ ace->a_perm = file_acl->g_access << 6;
+ ace->a_type = SMB_ACL_GROUP_OBJ;
+ break;
+
+ case 3:
+ ace->a_perm = file_acl->o_access << 6;
+ ace->a_type = SMB_ACL_OTHER;
+ break;
+
+ case 1:
+ ace->a_perm = file_acl->u_access << 6;
+ ace->a_type = SMB_ACL_USER_OBJ;
+ break;
+
+ default:
+ return(NULL);
+
+ }
+ ace->a_perm |= ((ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0);
+ ace->a_perm |= ((ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0);
+ ace->a_perm |= ((ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0);
+
+ memcpy(&result->acl[result->count],ace,sizeof(struct smb_acl_entry));
+ result->count++;
+ DEBUG(10,("ace->a_perm = %d\n",ace->a_perm));
+ DEBUG(10,("ace->a_type = %d\n",ace->a_type));
+ }
+
+
+ return result;
+
+
+}
+
+static ushort aixacl_smb_to_aixperm(SMB_ACL_PERM_T a_perm)
+{
+ ushort ret = (ushort)0;
+ if (a_perm & SMB_ACL_READ)
+ ret |= R_ACC;
+ if (a_perm & SMB_ACL_WRITE)
+ ret |= W_ACC;
+ if (a_perm & SMB_ACL_EXECUTE)
+ ret |= X_ACC;
+ return ret;
+}
+
+struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+{
+ struct smb_acl_entry *smb_entry = NULL;
+ struct acl *file_acl = NULL;
+ struct acl *file_acl_temp = NULL;
+ struct acl_entry *acl_entry = NULL;
+ struct ace_id *ace_id = NULL;
+ uint id_type;
+ uint user_id;
+ uint acl_length;
+ int i;
+
+ DEBUG(10,("Entering aixacl_smb_to_aixacl\n"));
+ /* AIX has no default ACL */
+ if(acltype == SMB_ACL_TYPE_DEFAULT)
+ return NULL;
+
+ acl_length = BUFSIZ;
+ file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
+ if(file_acl == NULL) {
+ errno = ENOMEM;
+ DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno));
+ return NULL;
+ }
+
+ memset(file_acl,0,BUFSIZ);
+
+ file_acl->acl_len = ACL_SIZ;
+ file_acl->acl_mode = S_IXACL;
+
+ for(i=0; i<theacl->count; i++ ) {
+ smb_entry = &(theacl->acl[i]);
+ id_type = smb_entry->a_type;
+ DEBUG(10,("The id_type is %d\n",id_type));
+
+ switch(id_type) {
+ case SMB_ACL_USER_OBJ:
+ file_acl->u_access = aixacl_smb_to_aixperm(smb_entry->a_perm);
+ continue;
+ case SMB_ACL_GROUP_OBJ:
+ file_acl->g_access = aixacl_smb_to_aixperm(smb_entry->a_perm);
+ continue;
+ case SMB_ACL_OTHER:
+ file_acl->o_access = aixacl_smb_to_aixperm(smb_entry->a_perm);
+ continue;
+ case SMB_ACL_MASK:
+ continue;
+ case SMB_ACL_GROUP:
+ break; /* process this */
+ case SMB_ACL_USER:
+ break; /* process this */
+ default: /* abnormal case */
+ DEBUG(10,("The id_type is unknown !\n"));
+ continue;
+ }
+
+ if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
+ acl_length += sizeof(struct acl_entry);
+ file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
+ if(file_acl_temp == NULL) {
+ SAFE_FREE(file_acl);
+ errno = ENOMEM;
+ DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno));
+ return NULL;
+ }
+
+ memcpy(file_acl_temp,file_acl,file_acl->acl_len);
+ SAFE_FREE(file_acl);
+ file_acl = file_acl_temp;
+ }
+
+ acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
+ file_acl->acl_len += sizeof(struct acl_entry);
+ acl_entry->ace_len = sizeof(struct acl_entry); /* contains 1 ace_id */
+ acl_entry->ace_access = aixacl_smb_to_aixperm(smb_entry->a_perm);
+
+ /* In order to use this, we'll need to wait until we can get denies */
+ /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
+ acl_entry->ace_type = ACC_SPECIFY; */
+
+ acl_entry->ace_type = ACC_SPECIFY;
+
+ ace_id = acl_entry->ace_id;
+
+ ace_id->id_type = (smb_entry->a_type==SMB_ACL_GROUP) ? ACEID_GROUP : ACEID_USER;
+ DEBUG(10,("The id type is %d\n",ace_id->id_type));
+ ace_id->id_len = sizeof(struct ace_id); /* contains 1 id_data */
+ ace_id->id_data[0] = (smb_entry->a_type==SMB_ACL_GROUP) ? smb_entry->gid : smb_entry->uid;
+ }
+
+ return file_acl;
+}
diff --git a/source/modules/vfs_audit.c b/source/modules/vfs_audit.c
index 9f5179a47ce..fb146c1ad4f 100644
--- a/source/modules/vfs_audit.c
+++ b/source/modules/vfs_audit.c
@@ -29,17 +29,17 @@
/* Function prototypes */
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr);
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user);
+static void audit_disconnect(vfs_handle_struct *handle);
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_rmdir(vfs_handle_struct *handle, const char *path);
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname);
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
+static int audit_unlink(vfs_handle_struct *handle, const char *path);
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode);
static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
@@ -120,7 +120,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle)
/* Implementation of vfs_ops. Pass everything on to the default
operation but log event first. */
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user)
{
int result;
@@ -129,24 +129,24 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con
syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n",
svc, user);
- result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+ result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
return result;
}
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void audit_disconnect(vfs_handle_struct *handle)
{
syslog(audit_syslog_priority(handle), "disconnected\n");
- SMB_VFS_NEXT_DISCONNECT(handle, conn);
+ SMB_VFS_NEXT_DISCONNECT(handle);
return;
}
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
{
SMB_STRUCT_DIR *result;
- result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+ result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
fname,
@@ -156,11 +156,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc
return result;
}
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n",
path,
@@ -170,11 +170,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_rmdir(vfs_handle_struct *handle, const char *path)
{
int result;
- result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+ result = SMB_VFS_NEXT_RMDIR(handle, path);
syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n",
path,
@@ -184,11 +184,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+ result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n",
fname, result,
@@ -213,11 +213,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
return result;
}
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
{
int result;
- result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+ result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
oldname, newname,
@@ -227,11 +227,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons
return result;
}
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_unlink(vfs_handle_struct *handle, const char *path)
{
int result;
- result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+ result = SMB_VFS_NEXT_UNLINK(handle, path);
syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
path,
@@ -241,11 +241,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons
return result;
}
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n",
path, mode,
@@ -255,11 +255,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n",
path, mode,
@@ -297,6 +297,7 @@ static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd
return result;
}
+NTSTATUS vfs_audit_init(void);
NTSTATUS vfs_audit_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "audit", audit_op_tuples);
diff --git a/source/modules/vfs_cacheprime.c b/source/modules/vfs_cacheprime.c
new file mode 100644
index 00000000000..61a92a02324
--- /dev/null
+++ b/source/modules/vfs_cacheprime.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) James Peach 2005-2006
+ *
+ * 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"
+
+/* Cache priming module.
+ *
+ * The purpose of this module is to do RAID stripe width reads to prime the
+ * buffer cache to do zero-copy I/O for subsequent sendfile calls. The idea is
+ * to do a single large read at the start of the file to make sure that most or
+ * all of the file is pulled into the buffer cache. Subsequent I/Os have
+ * reduced latency.
+ *
+ * Tunables.
+ *
+ * cacheprime:rsize Amount of readahead in bytes. This should be a
+ * multiple of the RAID stripe width.
+ * cacheprime:debug Debug level at which to emit messages.
+ */
+
+#define READAHEAD_MIN (128 * 1024) /* min is 128 KiB */
+#define READAHEAD_MAX (100 * 1024 * 1024) /* max is 100 MiB */
+
+#define MODULE "cacheprime"
+
+static int module_debug;
+static ssize_t g_readsz = 0;
+static void * g_readbuf = NULL;
+
+/* Prime the kernel buffer cache with data from the specified file. We use
+ * per-fsp data to make sure we only ever do this once. If pread is being
+ * emulated by seek/read/seek, when this will suck quite a lot.
+ */
+static BOOL prime_cache(
+ struct vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ SMB_OFF_T offset,
+ size_t count)
+{
+ SMB_OFF_T * last;
+ ssize_t nread;
+
+ last = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T);
+ if (!last) {
+ return False;
+ }
+
+ if (*last == -1) {
+ /* Readahead disabled. */
+ return False;
+ }
+
+ if ((*last + g_readsz) > (offset + count)) {
+ /* Skip readahead ... we've already been here. */
+ return False;
+ }
+
+ DEBUG(module_debug,
+ ("%s: doing readahead of %lld bytes at %lld for %s\n",
+ MODULE, (long long)g_readsz, (long long)*last,
+ fsp->fsp_name));
+
+ nread = sys_pread(fd, g_readbuf, g_readsz, *last);
+ if (nread < 0) {
+ *last = -1;
+ return False;
+ }
+
+ *last += nread;
+ return True;
+}
+
+static int cprime_connect(
+ struct vfs_handle_struct * handle,
+ const char * service,
+ const char * user)
+{
+ module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
+ if (g_readbuf) {
+ /* Only allocate g_readbuf once. If the config changes and
+ * another client multiplexes onto this smbd, we don't want
+ * to risk memory corruption.
+ */
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
+ }
+
+ g_readsz = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+ MODULE, "rsize", NULL));
+
+ if (g_readsz < READAHEAD_MIN) {
+ DEBUG(module_debug, ("%s: %ld bytes of readahead "
+ "requested, using minimum of %u\n",
+ MODULE, (long)g_readsz, READAHEAD_MIN));
+ g_readsz = READAHEAD_MIN;
+ } else if (g_readsz > READAHEAD_MAX) {
+ DEBUG(module_debug, ("%s: %ld bytes of readahead "
+ "requested, using maximum of %u\n",
+ MODULE, (long)g_readsz, READAHEAD_MAX));
+ g_readsz = READAHEAD_MAX;
+ }
+
+ if ((g_readbuf = SMB_MALLOC(g_readsz)) == NULL) {
+ /* Turn off readahead if we can't get a buffer. */
+ g_readsz = 0;
+ }
+
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static ssize_t cprime_sendfile(
+ struct vfs_handle_struct * handle,
+ int tofd,
+ files_struct * fsp,
+ int fromfd,
+ const DATA_BLOB * header,
+ SMB_OFF_T offset,
+ size_t count)
+{
+ if (g_readbuf && offset == 0) {
+ prime_cache(handle, fsp, fromfd, offset, count);
+ }
+
+ return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd,
+ header, offset, count);
+}
+
+static ssize_t cprime_read(
+ vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ void * data,
+ size_t count)
+{
+ SMB_OFF_T offset;
+
+ offset = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+ if (offset >= 0 && g_readbuf) {
+ prime_cache(handle, fsp, fd, offset, count);
+ SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET);
+ }
+
+ return SMB_VFS_NEXT_READ(handle, fsp, fd, data, count);
+}
+
+static ssize_t cprime_pread(
+ vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ void * data,
+ size_t count,
+ SMB_OFF_T offset)
+{
+ if (g_readbuf) {
+ prime_cache(handle, fsp, fd, offset, count);
+ }
+
+ return SMB_VFS_NEXT_PREAD(handle, fsp, fd, data, count, offset);
+}
+
+static vfs_op_tuple cprime_ops [] =
+{
+ {SMB_VFS_OP(cprime_sendfile),
+ SMB_VFS_OP_SENDFILE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(cprime_pread),
+ SMB_VFS_OP_PREAD, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(cprime_read),
+ SMB_VFS_OP_READ, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(cprime_connect),
+ SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+/* -------------------------------------------------------------------------
+ * Samba module initialisation entry point.
+ * -------------------------------------------------------------------------
+ */
+
+NTSTATUS vfs_cacheprime_init(void);
+NTSTATUS vfs_cacheprime_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, cprime_ops);
+}
+
+/* vim: set sw=4 ts=4 tw=79 et: */
diff --git a/source/modules/vfs_cap.c b/source/modules/vfs_cap.c
index b1bfcd75f2f..e058c9660c7 100644
--- a/source/modules/vfs_cap.c
+++ b/source/modules/vfs_cap.c
@@ -28,28 +28,28 @@
static char *capencode(char *to, const char *from);
static char *capdecode(char *to, const char *from);
-static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path,
+static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, const char *path,
BOOL small_query, SMB_BIG_UINT *bsize,
SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_DISK_FREE(handle, conn, cappath, small_query, bsize,
+ return SMB_VFS_NEXT_DISK_FREE(handle, cappath, small_query, bsize,
dfree, dsize);
}
-static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
{
pstring capname;
capencode(capname, fname);
- return SMB_VFS_NEXT_OPENDIR(handle, conn, capname, mask, attr);
+ return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr);
}
-static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
+static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
{
SMB_STRUCT_DIRENT *result;
DEBUG(3,("cap: cap_readdir\n"));
- result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+ result = SMB_VFS_NEXT_READDIR(handle, dirp);
if (result) {
DEBUG(3,("cap: cap_readdir: %s\n", result->d_name));
capdecode(result->d_name, result->d_name);
@@ -57,124 +57,124 @@ static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, connection_stru
return result;
}
-static int cap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int cap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_MKDIR(handle, conn, cappath, mode);
+ return SMB_VFS_NEXT_MKDIR(handle, cappath, mode);
}
-static int cap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_rmdir(vfs_handle_struct *handle, const char *path)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_RMDIR(handle, conn, cappath);
+ return SMB_VFS_NEXT_RMDIR(handle, cappath);
}
-static int cap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int cap_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
{
pstring capname;
DEBUG(3,("cap: cap_open for %s\n", fname));
capencode(capname, fname);
- return SMB_VFS_NEXT_OPEN(handle, conn, capname, flags, mode);
+ return SMB_VFS_NEXT_OPEN(handle, capname, fsp, flags, mode);
}
-static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
{
pstring capold, capnew;
capencode(capold, oldname);
capencode(capnew, newname);
- return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew);
+ return SMB_VFS_NEXT_RENAME(handle, capold, capnew);
}
-static int cap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+static int cap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
{
pstring capname;
capencode(capname, fname);
- return SMB_VFS_NEXT_STAT(handle, conn, capname, sbuf);
+ return SMB_VFS_NEXT_STAT(handle, capname, sbuf);
}
-static int cap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
+static int cap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_LSTAT(handle, conn, cappath, sbuf);
+ return SMB_VFS_NEXT_LSTAT(handle, cappath, sbuf);
}
-static int cap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_unlink(vfs_handle_struct *handle, const char *path)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_UNLINK(handle, conn, cappath);
+ return SMB_VFS_NEXT_UNLINK(handle, cappath);
}
-static int cap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_CHMOD(handle, conn, cappath, mode);
+ return SMB_VFS_NEXT_CHMOD(handle, cappath, mode);
}
-static int cap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_CHOWN(handle, conn, cappath, uid, gid);
+ return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid);
}
-static int cap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_chdir(vfs_handle_struct *handle, const char *path)
{
pstring cappath;
DEBUG(3,("cap: cap_chdir for %s\n", path));
capencode(cappath, path);
- return SMB_VFS_NEXT_CHDIR(handle, conn, cappath);
+ return SMB_VFS_NEXT_CHDIR(handle, cappath);
}
-static int cap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
+static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_UTIME(handle, conn, cappath, times);
+ return SMB_VFS_NEXT_UTIME(handle, cappath, times);
}
-static BOOL cap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+static BOOL cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
{
pstring capoldpath, capnewpath;
capencode(capoldpath, oldpath);
capencode(capnewpath, newpath);
- return SMB_VFS_NEXT_SYMLINK(handle, conn, capoldpath, capnewpath);
+ return SMB_VFS_NEXT_SYMLINK(handle, capoldpath, capnewpath);
}
-static BOOL cap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
+static BOOL cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_READLINK(handle, conn, cappath, buf, bufsiz);
+ return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
}
-static int cap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
+static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
{
pstring capoldpath, capnewpath;
capencode(capoldpath, oldpath);
capencode(capnewpath, newpath);
- return SMB_VFS_NEXT_LINK(handle, conn, capoldpath, capnewpath);
+ return SMB_VFS_NEXT_LINK(handle, capoldpath, capnewpath);
}
-static int cap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
+static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_MKNOD(handle, conn, cappath, mode, dev);
+ return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
}
-static char *cap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
+static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
{
/* monyo need capencode'ed and capdecode'ed? */
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+ return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
}
static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
@@ -184,7 +184,7 @@ static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const c
return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, capname, security_info_sent, psd);
}
-static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
+static int cap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
{
pstring capname;
capencode(capname, name);
@@ -194,45 +194,45 @@ static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, con
errno = ENOSYS;
return -1;
}
- return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, capname, mode);
+ return SMB_VFS_NEXT_CHMOD_ACL(handle, capname, mode);
}
-static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
+static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type)
{
pstring cappath_p;
capencode(cappath_p, path_p);
- return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, cappath_p, type);
+ return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath_p, type);
}
-static int cap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
{
pstring capname;
capencode(capname, name);
- return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, capname, acltype, theacl);
+ return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, capname, acltype, theacl);
}
-static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, cappath);
+ return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
}
-static ssize_t cap_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
+static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_GETXATTR(handle, conn, cappath, capname, value, size);
+ return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
}
-static ssize_t cap_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
+static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t
size)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_LGETXATTR(handle, conn, cappath, capname, value, size);
+ return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size);
}
static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
@@ -242,34 +242,34 @@ static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp
return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, capname, value, size);
}
-static ssize_t cap_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_LISTXATTR(handle, conn, cappath, list, size);
+ return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
}
-static ssize_t cap_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
+static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_LLISTXATTR(handle, conn, cappath, list, size);
+ return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size);
}
-static int cap_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, cappath, capname);
+ return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
}
-static int cap_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
+static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, cappath, capname);
+ return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname);
}
static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
@@ -279,20 +279,20 @@ static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,
return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, capname);
}
-static int cap_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_SETXATTR(handle, conn, cappath, capname, value, size, flags);
+ return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
}
-static int cap_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
+static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
{
pstring cappath, capname;
capencode(cappath, path);
capencode(capname, name);
- return SMB_VFS_NEXT_LSETXATTR(handle, conn, cappath, capname, value, size, flags);
+ return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags);
}
static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
@@ -362,6 +362,7 @@ static vfs_op_tuple cap_op_tuples[] = {
{NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_cap_init(void);
NTSTATUS vfs_cap_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples);
diff --git a/source/modules/vfs_catia.c b/source/modules/vfs_catia.c
index 69735de3f43..478dab6cbed 100644
--- a/source/modules/vfs_catia.c
+++ b/source/modules/vfs_catia.c
@@ -71,20 +71,20 @@ static void to_unix(char *s)
catia_string_replace(s, '\xb1', ' ');
}
-static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle, connection_struct
- *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
+ const char *fname, const char *mask, uint32 attr)
{
pstring name;
pstrcpy(name, fname);
to_unix(name);
- return SMB_VFS_NEXT_OPENDIR(handle, conn, name, mask, attr);
+ return SMB_VFS_NEXT_OPENDIR(handle, name, mask, attr);
}
static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle,
- connection_struct *conn, SMB_STRUCT_DIR *dirp)
+ SMB_STRUCT_DIR *dirp)
{
- SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+ SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, dirp);
if (result == NULL)
return result;
@@ -93,18 +93,18 @@ static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle,
return result;
}
-static int catia_open(vfs_handle_struct *handle, connection_struct *conn,
- const char *fname, int flags, mode_t mode)
+static int catia_open(vfs_handle_struct *handle,
+ const char *fname, files_struct *fsp, int flags, mode_t mode)
{
pstring name;
pstrcpy(name, fname);
to_unix(name);
- return SMB_VFS_NEXT_OPEN(handle, conn, name, flags, mode);
+ return SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode);
}
-static int catia_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_rename(vfs_handle_struct *handle,
const char *oldname, const char *newname)
{
pstring oname, nname;
@@ -117,114 +117,112 @@ static int catia_rename(vfs_handle_struct *handle, connection_struct *conn,
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);
+ return SMB_VFS_NEXT_RENAME(handle, oname, nname);
}
-static int catia_stat(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_stat(vfs_handle_struct *handle,
const char *fname, SMB_STRUCT_STAT *sbuf)
{
pstring name;
pstrcpy(name, fname);
to_unix(name);
- return SMB_VFS_NEXT_STAT(handle, conn, name, sbuf);
+ return SMB_VFS_NEXT_STAT(handle, name, sbuf);
}
-static int catia_lstat(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_lstat(vfs_handle_struct *handle,
const char *path, SMB_STRUCT_STAT *sbuf)
{
pstring name;
pstrcpy(name, path);
to_unix(name);
- return SMB_VFS_NEXT_LSTAT(handle, conn, name, sbuf);
+ return SMB_VFS_NEXT_LSTAT(handle, name, sbuf);
}
-static int catia_unlink(vfs_handle_struct *handle, connection_struct *conn,
- const char *path)
+static int catia_unlink(vfs_handle_struct *handle, const char *path)
{
pstring name;
pstrcpy(name, path);
to_unix(name);
- return SMB_VFS_NEXT_UNLINK(handle, conn, name);
+ return SMB_VFS_NEXT_UNLINK(handle, name);
}
-static int catia_chmod(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_chmod(vfs_handle_struct *handle,
const char *path, mode_t mode)
{
pstring name;
pstrcpy(name, path);
to_unix(name);
- return SMB_VFS_NEXT_CHMOD(handle, conn, name, mode);
+ return SMB_VFS_NEXT_CHMOD(handle, name, mode);
}
-static int catia_chown(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_chown(vfs_handle_struct *handle,
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);
+ return SMB_VFS_NEXT_CHOWN(handle, name, uid, gid);
}
-static int catia_chdir(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_chdir(vfs_handle_struct *handle,
const char *path)
{
pstring name;
pstrcpy(name, path);
to_unix(name);
- return SMB_VFS_NEXT_CHDIR(handle, conn, name);
+ return SMB_VFS_NEXT_CHDIR(handle, name);
}
-static char *catia_getwd(vfs_handle_struct *handle, connection_struct *conn,
- char *buf)
+static char *catia_getwd(vfs_handle_struct *handle, char *buf)
{
- return SMB_VFS_NEXT_GETWD(handle, conn, buf);
+ return SMB_VFS_NEXT_GETWD(handle, buf);
}
-static int catia_utime(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_utime(vfs_handle_struct *handle,
const char *path, struct utimbuf *times)
{
- return SMB_VFS_NEXT_UTIME(handle, conn, path, times);
+ return SMB_VFS_NEXT_UTIME(handle, path, times);
}
-static BOOL catia_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static BOOL catia_symlink(vfs_handle_struct *handle,
const char *oldpath, const char *newpath)
{
- return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
+ return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
}
-static BOOL catia_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static BOOL catia_readlink(vfs_handle_struct *handle,
const char *path, char *buf, size_t bufsiz)
{
- return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
+ return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
}
-static int catia_link(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_link(vfs_handle_struct *handle,
const char *oldpath, const char *newpath)
{
- return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
+ return SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
}
-static int catia_mknod(vfs_handle_struct *handle, connection_struct *conn,
+static int catia_mknod(vfs_handle_struct *handle,
const char *path, mode_t mode, SMB_DEV_T dev)
{
- return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev);
+ return SMB_VFS_NEXT_MKNOD(handle, path, mode, dev);
}
-static char *catia_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *catia_realpath(vfs_handle_struct *handle,
const char *path, char *resolved_path)
{
- return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+ return SMB_VFS_NEXT_REALPATH(handle, 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)
+ struct security_descriptor **ppdesc)
{
return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info,
ppdesc);
@@ -232,13 +230,13 @@ static size_t catia_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
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)
+ struct security_descriptor *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,
+static int catia_chmod_acl(vfs_handle_struct *handle,
const char *name, mode_t mode)
{
/* If the underlying VFS doesn't have ACL support... */
@@ -246,7 +244,7 @@ static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
errno = ENOSYS;
return -1;
}
- return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode);
+ return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
}
/* VFS operations structure */
@@ -310,7 +308,8 @@ SMB_VFS_LAYER_TRANSPARENT},
SMB_VFS_LAYER_NOOP}
};
-NTSTATUS init_module(void)
+NTSTATUS vfs_catia_init(void);
+NTSTATUS vfs_catia_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
catia_op_tuples);
diff --git a/source/modules/vfs_commit.c b/source/modules/vfs_commit.c
new file mode 100644
index 00000000000..4407490d223
--- /dev/null
+++ b/source/modules/vfs_commit.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) James Peach 2006
+ *
+ * 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"
+
+/* Commit data module.
+ *
+ * The purpose of this module is to flush data to disk at regular intervals,
+ * just like the NFS commit operation. There's two rationales for this. First,
+ * it minimises the data loss in case of a power outage without incurring
+ * the poor performance of synchronous I/O. Second, a steady flush rate
+ * can produce better throughput than suddenly dumping massive amounts of
+ * writes onto a disk.
+ *
+ * Tunables:
+ *
+ * commit: dthresh Amount of dirty data that can accumulate
+ * before we commit (sync) it.
+ *
+ * commit: debug Debug level at which to emit messages.
+ *
+ */
+
+#define MODULE "commit"
+
+static int module_debug;
+
+struct commit_info
+{
+ SMB_OFF_T dbytes; /* Dirty (uncommitted) bytes */
+ SMB_OFF_T dthresh; /* Dirty data threshold */
+};
+
+static void commit_all(
+ struct vfs_handle_struct * handle,
+ files_struct * fsp)
+{
+ struct commit_info *c;
+
+ if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+ if (c->dbytes) {
+ DEBUG(module_debug,
+ ("%s: flushing %lu dirty bytes\n",
+ MODULE, (unsigned long)c->dbytes));
+
+ fdatasync(fsp->fh->fd);
+ c->dbytes = 0;
+ }
+ }
+}
+
+static void commit(
+ struct vfs_handle_struct * handle,
+ files_struct * fsp,
+ ssize_t last_write)
+{
+ struct commit_info *c;
+
+ if ((c = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+
+ if (last_write > 0) {
+ c->dbytes += last_write;
+ }
+
+ if (c->dbytes > c->dthresh) {
+ DEBUG(module_debug,
+ ("%s: flushing %lu dirty bytes\n",
+ MODULE, (unsigned long)c->dbytes));
+
+ fdatasync(fsp->fh->fd);
+ c->dbytes = 0;
+ }
+ }
+}
+
+static int commit_connect(
+ struct vfs_handle_struct * handle,
+ const char * service,
+ const char * user)
+{
+ module_debug = lp_parm_int(SNUM(handle->conn), MODULE, "debug", 100);
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static int commit_open(
+ vfs_handle_struct * handle,
+ const char * fname,
+ files_struct * fsp,
+ int flags,
+ mode_t mode)
+{
+ SMB_OFF_T dthresh;
+
+ /* Don't bother with read-only files. */
+ if ((flags & O_ACCMODE) == O_RDONLY) {
+ return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+ }
+
+ dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+ MODULE, "dthresh", NULL));
+
+ if (dthresh > 0) {
+ struct commit_info * c;
+ c = VFS_ADD_FSP_EXTENSION(handle, fsp, struct commit_info);
+ if (c) {
+ c->dthresh = dthresh;
+ c->dbytes = 0;
+ }
+ }
+
+ return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+}
+
+static ssize_t commit_write(
+ vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ void * data,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, count);
+ commit(handle, fsp, ret);
+
+ return ret;
+}
+
+static ssize_t commit_pwrite(
+ vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ void * data,
+ size_t count,
+ SMB_OFF_T offset)
+{
+ ssize_t ret;
+
+ ret = SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, count, offset);
+ commit(handle, fsp, ret);
+
+ return ret;
+}
+
+static ssize_t commit_close(
+ vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd)
+{
+ commit_all(handle, fsp);
+ return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
+}
+
+static vfs_op_tuple commit_ops [] =
+{
+ {SMB_VFS_OP(commit_open),
+ SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(commit_close),
+ SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(commit_write),
+ SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(commit_pwrite),
+ SMB_VFS_OP_PWRITE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(commit_connect),
+ SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_commit_init(void);
+NTSTATUS vfs_commit_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE, commit_ops);
+}
+
diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c
new file mode 100644
index 00000000000..bd7bea5258a
--- /dev/null
+++ b/source/modules/vfs_default.c
@@ -0,0 +1,1389 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap disk only vfs functions to sidestep dodgy compilers.
+ Copyright (C) Tim Potter 1998
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+/* Check for NULL pointer parameters in vfswrap_* functions */
+
+/* We don't want to have NULL function pointers lying around. Someone
+ is sure to try and execute them. These stubs are used to prevent
+ this possibility. */
+
+static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
+{
+ return 0; /* Return >= 0 for success */
+}
+
+static void vfswrap_disconnect(vfs_handle_struct *handle)
+{
+}
+
+/* Disk operations */
+
+static SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+ SMB_BIG_UINT result;
+
+ result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
+ return result;
+}
+
+static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+ int result;
+
+ START_PROFILE(syscall_get_quota);
+ result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
+ END_PROFILE(syscall_get_quota);
+ return result;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+ int result;
+
+ START_PROFILE(syscall_set_quota);
+ result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
+ END_PROFILE(syscall_set_quota);
+ return result;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+ errno = ENOSYS;
+ return -1; /* Not implemented. */
+}
+
+static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
+{
+ return sys_statvfs(path, statbuf);
+}
+
+/* Directory operations */
+
+static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
+{
+ SMB_STRUCT_DIR *result;
+
+ START_PROFILE(syscall_opendir);
+ result = sys_opendir(fname);
+ END_PROFILE(syscall_opendir);
+ return result;
+}
+
+static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
+{
+ SMB_STRUCT_DIRENT *result;
+
+ START_PROFILE(syscall_readdir);
+ result = sys_readdir(dirp);
+ END_PROFILE(syscall_readdir);
+ return result;
+}
+
+static void vfswrap_seekdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp, long offset)
+{
+ START_PROFILE(syscall_seekdir);
+ sys_seekdir(dirp, offset);
+ END_PROFILE(syscall_seekdir);
+}
+
+static long vfswrap_telldir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
+{
+ long result;
+ START_PROFILE(syscall_telldir);
+ result = sys_telldir(dirp);
+ END_PROFILE(syscall_telldir);
+ return result;
+}
+
+static void vfswrap_rewinddir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
+{
+ START_PROFILE(syscall_rewinddir);
+ sys_rewinddir(dirp);
+ END_PROFILE(syscall_rewinddir);
+}
+
+static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
+{
+ int result;
+ BOOL has_dacl = False;
+
+ START_PROFILE(syscall_mkdir);
+
+ if (lp_inherit_acls(SNUM(handle->conn)) && (has_dacl = directory_has_default_acl(handle->conn, parent_dirname(path))))
+ mode = 0777;
+
+ result = mkdir(path, mode);
+
+ if (result == 0 && !has_dacl) {
+ /*
+ * We need to do this as the default behavior of POSIX ACLs
+ * is to set the mask to be the requested group permission
+ * bits, not the group permission bits to be the requested
+ * group permission bits. This is not what we want, as it will
+ * mess up any inherited ACL bits that were set. JRA.
+ */
+ int saved_errno = errno; /* We may get ENOSYS */
+ if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
+ errno = saved_errno;
+ }
+
+ END_PROFILE(syscall_mkdir);
+ return result;
+}
+
+static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
+{
+ int result;
+
+ START_PROFILE(syscall_rmdir);
+ result = rmdir(path);
+ END_PROFILE(syscall_rmdir);
+ return result;
+}
+
+static int vfswrap_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
+{
+ int result;
+
+ START_PROFILE(syscall_closedir);
+ result = sys_closedir(dirp);
+ END_PROFILE(syscall_closedir);
+ return result;
+}
+
+/* File operations */
+
+static int vfswrap_open(vfs_handle_struct *handle, const char *fname,
+ files_struct *fsp, int flags, mode_t mode)
+{
+ int result;
+
+ START_PROFILE(syscall_open);
+ result = sys_open(fname, flags, mode);
+ END_PROFILE(syscall_open);
+ return result;
+}
+
+static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ int result;
+
+ START_PROFILE(syscall_close);
+
+ result = close(fd);
+ END_PROFILE(syscall_close);
+ return result;
+}
+
+static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
+{
+ ssize_t result;
+
+ START_PROFILE_BYTES(syscall_read, n);
+ result = sys_read(fd, data, n);
+ END_PROFILE(syscall_read);
+ return result;
+}
+
+static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
+ size_t n, SMB_OFF_T offset)
+{
+ ssize_t result;
+
+#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
+ START_PROFILE_BYTES(syscall_pread, n);
+ result = sys_pread(fd, data, n, offset);
+ END_PROFILE(syscall_pread);
+
+ if (result == -1 && errno == ESPIPE) {
+ /* Maintain the fiction that pipes can be seeked (sought?) on. */
+ result = SMB_VFS_READ(fsp, fd, data, n);
+ fsp->fh->pos = 0;
+ }
+
+#else /* HAVE_PREAD */
+ SMB_OFF_T curr;
+ int lerrno;
+
+ curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+ if (curr == -1 && errno == ESPIPE) {
+ /* Maintain the fiction that pipes can be seeked (sought?) on. */
+ result = SMB_VFS_READ(fsp, fd, data, n);
+ fsp->fh->pos = 0;
+ return result;
+ }
+
+ if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
+ return -1;
+ }
+
+ errno = 0;
+ result = SMB_VFS_READ(fsp, fd, data, n);
+ lerrno = errno;
+
+ SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
+ errno = lerrno;
+
+#endif /* HAVE_PREAD */
+
+ return result;
+}
+
+static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
+{
+ ssize_t result;
+
+ START_PROFILE_BYTES(syscall_write, n);
+ result = sys_write(fd, data, n);
+ END_PROFILE(syscall_write);
+ return result;
+}
+
+static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
+ size_t n, SMB_OFF_T offset)
+{
+ ssize_t result;
+
+#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
+ START_PROFILE_BYTES(syscall_pwrite, n);
+ result = sys_pwrite(fd, data, n, offset);
+ END_PROFILE(syscall_pwrite);
+
+ if (result == -1 && errno == ESPIPE) {
+ /* Maintain the fiction that pipes can be sought on. */
+ result = SMB_VFS_WRITE(fsp, fd, data, n);
+ }
+
+#else /* HAVE_PWRITE */
+ SMB_OFF_T curr;
+ int lerrno;
+
+ curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+ if (curr == -1) {
+ return -1;
+ }
+
+ if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
+ return -1;
+ }
+
+ result = SMB_VFS_WRITE(fsp, fd, data, n);
+ lerrno = errno;
+
+ SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
+ errno = lerrno;
+
+#endif /* HAVE_PWRITE */
+
+ return result;
+}
+
+static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
+{
+ SMB_OFF_T result = 0;
+
+ START_PROFILE(syscall_lseek);
+
+ /* Cope with 'stat' file opens. */
+ if (filedes != -1)
+ result = sys_lseek(filedes, offset, whence);
+
+ /*
+ * We want to maintain the fiction that we can seek
+ * on a fifo for file system purposes. This allows
+ * people to set up UNIX fifo's that feed data to Windows
+ * applications. JRA.
+ */
+
+ if((result == -1) && (errno == ESPIPE)) {
+ result = 0;
+ errno = 0;
+ }
+
+ END_PROFILE(syscall_lseek);
+ return result;
+}
+
+static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
+ SMB_OFF_T offset, size_t n)
+{
+ ssize_t result;
+
+ START_PROFILE_BYTES(syscall_sendfile, n);
+ result = sys_sendfile(tofd, fromfd, hdr, offset, n);
+ END_PROFILE(syscall_sendfile);
+ return result;
+}
+
+/*********************************************************
+ For rename across filesystems Patch from Warren Birnbaum
+ <warrenb@hpcvscdp.cv.hp.com>
+**********************************************************/
+
+static int copy_reg(const char *source, const char *dest)
+{
+ SMB_STRUCT_STAT source_stats;
+ int saved_errno;
+ int ifd = -1;
+ int ofd = -1;
+
+ if (sys_lstat (source, &source_stats) == -1)
+ return -1;
+
+ if (!S_ISREG (source_stats.st_mode))
+ return -1;
+
+ if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
+ return -1;
+
+ if (unlink (dest) && errno != ENOENT)
+ return -1;
+
+#ifdef O_NOFOLLOW
+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
+#else
+ if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
+#endif
+ goto err;
+
+ if (transfer_file(ifd, ofd, (size_t)-1) == -1)
+ goto err;
+
+ /*
+ * Try to preserve ownership. For non-root it might fail, but that's ok.
+ * But root probably wants to know, e.g. if NFS disallows it.
+ */
+
+#ifdef HAVE_FCHOWN
+ if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
+#else
+ if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
+#endif
+ goto err;
+
+ /*
+ * fchown turns off set[ug]id bits for non-root,
+ * so do the chmod last.
+ */
+
+#if defined(HAVE_FCHMOD)
+ if (fchmod (ofd, source_stats.st_mode & 07777))
+#else
+ if (chmod (dest, source_stats.st_mode & 07777))
+#endif
+ goto err;
+
+ if (close (ifd) == -1)
+ goto err;
+
+ if (close (ofd) == -1)
+ return -1;
+
+ /* Try to copy the old file's modtime and access time. */
+ {
+ struct utimbuf tv;
+
+ tv.actime = source_stats.st_atime;
+ tv.modtime = source_stats.st_mtime;
+ utime(dest, &tv);
+ }
+
+ if (unlink (source) == -1)
+ return -1;
+
+ return 0;
+
+ err:
+
+ saved_errno = errno;
+ if (ifd != -1)
+ close(ifd);
+ if (ofd != -1)
+ close(ofd);
+ errno = saved_errno;
+ return -1;
+}
+
+static int vfswrap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
+{
+ int result;
+
+ START_PROFILE(syscall_rename);
+ result = rename(oldname, newname);
+ if (errno == EXDEV) {
+ /* Rename across filesystems needed. */
+ result = copy_reg(oldname, newname);
+ }
+
+ END_PROFILE(syscall_rename);
+ return result;
+}
+
+static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+#ifdef HAVE_FSYNC
+ int result;
+
+ START_PROFILE(syscall_fsync);
+ result = fsync(fd);
+ END_PROFILE(syscall_fsync);
+ return result;
+#else
+ return 0;
+#endif
+}
+
+static int vfswrap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ int result;
+
+ START_PROFILE(syscall_stat);
+ result = sys_stat(fname, sbuf);
+ END_PROFILE(syscall_stat);
+ return result;
+}
+
+static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
+{
+ int result;
+
+ START_PROFILE(syscall_fstat);
+ result = sys_fstat(fd, sbuf);
+ END_PROFILE(syscall_fstat);
+ return result;
+}
+
+int vfswrap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
+{
+ int result;
+
+ START_PROFILE(syscall_lstat);
+ result = sys_lstat(path, sbuf);
+ END_PROFILE(syscall_lstat);
+ return result;
+}
+
+static int vfswrap_unlink(vfs_handle_struct *handle, const char *path)
+{
+ int result;
+
+ START_PROFILE(syscall_unlink);
+ result = unlink(path);
+ END_PROFILE(syscall_unlink);
+ return result;
+}
+
+static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
+{
+ int result;
+
+ START_PROFILE(syscall_chmod);
+
+ /*
+ * We need to do this due to the fact that the default POSIX ACL
+ * chmod modifies the ACL *mask* for the group owner, not the
+ * group owner bits directly. JRA.
+ */
+
+
+ {
+ int saved_errno = errno; /* We might get ENOSYS */
+ if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
+ END_PROFILE(syscall_chmod);
+ return result;
+ }
+ /* Error - return the old errno. */
+ errno = saved_errno;
+ }
+
+ result = chmod(path, mode);
+ END_PROFILE(syscall_chmod);
+ return result;
+}
+
+static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+ int result;
+
+ START_PROFILE(syscall_fchmod);
+
+ /*
+ * We need to do this due to the fact that the default POSIX ACL
+ * chmod modifies the ACL *mask* for the group owner, not the
+ * group owner bits directly. JRA.
+ */
+
+ {
+ int saved_errno = errno; /* We might get ENOSYS */
+ if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
+ END_PROFILE(syscall_fchmod);
+ return result;
+ }
+ /* Error - return the old errno. */
+ errno = saved_errno;
+ }
+
+#if defined(HAVE_FCHMOD)
+ result = fchmod(fd, mode);
+#else
+ result = -1;
+ errno = ENOSYS;
+#endif
+
+ END_PROFILE(syscall_fchmod);
+ return result;
+}
+
+static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
+{
+ int result;
+
+ START_PROFILE(syscall_chown);
+ result = sys_chown(path, uid, gid);
+ END_PROFILE(syscall_chown);
+ return result;
+}
+
+static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
+{
+#ifdef HAVE_FCHOWN
+ int result;
+
+ START_PROFILE(syscall_fchown);
+ result = fchown(fd, uid, gid);
+ END_PROFILE(syscall_fchown);
+ return result;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
+{
+ int result;
+
+ START_PROFILE(syscall_chdir);
+ result = chdir(path);
+ END_PROFILE(syscall_chdir);
+ return result;
+}
+
+static char *vfswrap_getwd(vfs_handle_struct *handle, char *path)
+{
+ char *result;
+
+ START_PROFILE(syscall_getwd);
+ result = sys_getwd(path);
+ END_PROFILE(syscall_getwd);
+ return result;
+}
+
+static int vfswrap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+{
+ int result;
+
+ START_PROFILE(syscall_utime);
+ result = utime(path, times);
+ END_PROFILE(syscall_utime);
+ return result;
+}
+
+/*********************************************************************
+ A version of ftruncate that will write the space on disk if strict
+ allocate is set.
+**********************************************************************/
+
+static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
+{
+ SMB_STRUCT_STAT st;
+ SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+ unsigned char zero_space[4096];
+ SMB_OFF_T space_to_write;
+
+ if (currpos == -1)
+ return -1;
+
+ if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
+ return -1;
+
+ space_to_write = len - st.st_size;
+
+#ifdef S_ISFIFO
+ if (S_ISFIFO(st.st_mode))
+ return 0;
+#endif
+
+ if (st.st_size == len)
+ return 0;
+
+ /* Shrink - just ftruncate. */
+ if (st.st_size > len)
+ return sys_ftruncate(fd, len);
+
+ /* Write out the real space on disk. */
+ if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
+ return -1;
+
+ space_to_write = len - st.st_size;
+
+ memset(zero_space, '\0', sizeof(zero_space));
+ while ( space_to_write > 0) {
+ SMB_OFF_T retlen;
+ SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
+
+ retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write);
+ if (retlen <= 0)
+ return -1;
+
+ space_to_write -= retlen;
+ }
+
+ /* Seek to where we were */
+ if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
+ return -1;
+
+ return 0;
+}
+
+static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
+{
+ int result = -1;
+ SMB_STRUCT_STAT st;
+ char c = 0;
+ SMB_OFF_T currpos;
+
+ START_PROFILE(syscall_ftruncate);
+
+ if (lp_strict_allocate(SNUM(fsp->conn))) {
+ result = strict_allocate_ftruncate(handle, fsp, fd, len);
+ END_PROFILE(syscall_ftruncate);
+ return result;
+ }
+
+ /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
+ sys_ftruncate if the system supports it. Then I discovered that
+ you can have some filesystems that support ftruncate
+ expansion and some that don't! On Linux fat can't do
+ ftruncate extend but ext2 can. */
+
+ result = sys_ftruncate(fd, len);
+ if (result == 0)
+ goto done;
+
+ /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
+ extend a file with ftruncate. Provide alternate implementation
+ for this */
+ currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
+ if (currpos == -1) {
+ goto done;
+ }
+
+ /* Do an fstat to see if the file is longer than the requested
+ size in which case the ftruncate above should have
+ succeeded or shorter, in which case seek to len - 1 and
+ write 1 byte of zero */
+ if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
+ goto done;
+ }
+
+#ifdef S_ISFIFO
+ if (S_ISFIFO(st.st_mode)) {
+ result = 0;
+ goto done;
+ }
+#endif
+
+ if (st.st_size == len) {
+ result = 0;
+ goto done;
+ }
+
+ if (st.st_size > len) {
+ /* the sys_ftruncate should have worked */
+ goto done;
+ }
+
+ if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
+ goto done;
+
+ if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
+ goto done;
+
+ /* Seek to where we were */
+ if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
+ goto done;
+ result = 0;
+
+ done:
+
+ END_PROFILE(syscall_ftruncate);
+ return result;
+}
+
+static BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
+{
+ BOOL result;
+
+ START_PROFILE(syscall_fcntl_lock);
+ result = fcntl_lock(fd, op, offset, count, type);
+ END_PROFILE(syscall_fcntl_lock);
+ return result;
+}
+
+static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp, int fd,
+ uint32 share_mode)
+{
+ START_PROFILE(syscall_kernel_flock);
+ kernel_flock(fd, share_mode);
+ END_PROFILE(syscall_kernel_flock);
+ return 0;
+}
+
+static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+{
+ BOOL result;
+
+ START_PROFILE(syscall_fcntl_getlock);
+ result = fcntl_getlock(fd, poffset, pcount, ptype, ppid);
+ END_PROFILE(syscall_fcntl_getlock);
+ return result;
+}
+
+static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, int fd,
+ int leasetype)
+{
+ int result;
+
+ START_PROFILE(syscall_linux_setlease);
+
+#ifdef LINUX
+ /* first set the signal handler */
+ if(linux_set_lease_sighandler(fd) == -1)
+ return -1;
+
+ result = linux_setlease(fd, leasetype);
+
+#endif
+ END_PROFILE(syscall_linux_setlease);
+ return result;
+}
+
+static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
+{
+ int result;
+
+ START_PROFILE(syscall_symlink);
+ result = sys_symlink(oldpath, newpath);
+ END_PROFILE(syscall_symlink);
+ return result;
+}
+
+static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
+{
+ int result;
+
+ START_PROFILE(syscall_readlink);
+ result = sys_readlink(path, buf, bufsiz);
+ END_PROFILE(syscall_readlink);
+ return result;
+}
+
+static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
+{
+ int result;
+
+ START_PROFILE(syscall_link);
+ result = sys_link(oldpath, newpath);
+ END_PROFILE(syscall_link);
+ return result;
+}
+
+static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
+{
+ int result;
+
+ START_PROFILE(syscall_mknod);
+ result = sys_mknod(pathname, mode, dev);
+ END_PROFILE(syscall_mknod);
+ return result;
+}
+
+static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
+{
+ char *result;
+
+ START_PROFILE(syscall_realpath);
+ result = sys_realpath(path, resolved_path);
+ END_PROFILE(syscall_realpath);
+ return result;
+}
+
+static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
+ struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data, void *handle)
+{
+ /*
+ * So far inotify is the only supported default notify mechanism. If
+ * another platform like the the BSD's or a proprietary Unix comes
+ * along and wants another default, we can play the same trick we
+ * played with Posix ACLs.
+ *
+ * Until that is the case, hard-code inotify here.
+ */
+#ifdef HAVE_INOTIFY
+ if (lp_kernel_change_notify(ctx->conn->params)) {
+ return inotify_watch(ctx, e, callback, private_data, handle);
+ }
+#endif
+ /*
+ * Do nothing, leave everything to notify_internal.c
+ */
+ return NT_STATUS_OK;
+}
+
+static size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
+{
+ size_t result;
+
+ START_PROFILE(fget_nt_acl);
+ result = get_nt_acl(fsp, security_info, ppdesc);
+ END_PROFILE(fget_nt_acl);
+ return result;
+}
+
+static size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
+{
+ size_t result;
+
+ START_PROFILE(get_nt_acl);
+ result = get_nt_acl(fsp, security_info, ppdesc);
+ END_PROFILE(get_nt_acl);
+ return result;
+}
+
+static BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
+{
+ BOOL result;
+
+ START_PROFILE(fset_nt_acl);
+ result = set_nt_acl(fsp, security_info_sent, psd);
+ END_PROFILE(fset_nt_acl);
+ return result;
+}
+
+static BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
+{
+ BOOL result;
+
+ START_PROFILE(set_nt_acl);
+ result = set_nt_acl(fsp, security_info_sent, psd);
+ END_PROFILE(set_nt_acl);
+ return result;
+}
+
+static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
+{
+#ifdef HAVE_NO_ACL
+ errno = ENOSYS;
+ return -1;
+#else
+ int result;
+
+ START_PROFILE(chmod_acl);
+ result = chmod_acl(handle->conn, name, mode);
+ END_PROFILE(chmod_acl);
+ return result;
+#endif
+}
+
+static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
+{
+#ifdef HAVE_NO_ACL
+ errno = ENOSYS;
+ return -1;
+#else
+ int result;
+
+ START_PROFILE(fchmod_acl);
+ result = fchmod_acl(fsp, fd, mode);
+ END_PROFILE(fchmod_acl);
+ return result;
+#endif
+}
+
+static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
+{
+ return sys_acl_get_entry(theacl, entry_id, entry_p);
+}
+
+static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
+{
+ return sys_acl_get_tag_type(entry_d, tag_type_p);
+}
+
+static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
+{
+ return sys_acl_get_permset(entry_d, permset_p);
+}
+
+static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry_d)
+{
+ return sys_acl_get_qualifier(entry_d);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, const char *path_p, SMB_ACL_TYPE_T type)
+{
+ return sys_acl_get_file(handle, path_p, type);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
+{
+ return sys_acl_get_fd(handle, fsp, fd);
+}
+
+static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset)
+{
+ return sys_acl_clear_perms(permset);
+}
+
+static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ return sys_acl_add_perm(permset, perm);
+}
+
+static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, SMB_ACL_T theacl, ssize_t *plen)
+{
+ return sys_acl_to_text(theacl, plen);
+}
+
+static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, int count)
+{
+ return sys_acl_init(count);
+}
+
+static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
+{
+ return sys_acl_create_entry(pacl, pentry);
+}
+
+static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
+{
+ return sys_acl_set_tag_type(entry, tagtype);
+}
+
+static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, void *qual)
+{
+ return sys_acl_set_qualifier(entry, qual);
+}
+
+static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
+{
+ return sys_acl_set_permset(entry, permset);
+}
+
+static int vfswrap_sys_acl_valid(vfs_handle_struct *handle, SMB_ACL_T theacl )
+{
+ return sys_acl_valid(theacl );
+}
+
+static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
+{
+ return sys_acl_set_file(handle, name, acltype, theacl);
+}
+
+static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
+{
+ return sys_acl_set_fd(handle, fsp, fd, theacl);
+}
+
+static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
+{
+ return sys_acl_delete_def_file(handle, path);
+}
+
+static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
+{
+ return sys_acl_get_perm(permset, perm);
+}
+
+static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, char *text)
+{
+ return sys_acl_free_text(text);
+}
+
+static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, SMB_ACL_T posix_acl)
+{
+ return sys_acl_free_acl(posix_acl);
+}
+
+static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, void *qualifier, SMB_ACL_TAG_T tagtype)
+{
+ return sys_acl_free_qualifier(qualifier, tagtype);
+}
+
+/****************************************************************
+ Extended attribute operations.
+*****************************************************************/
+
+static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
+{
+ return sys_getxattr(path, name, value, size);
+}
+
+static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
+{
+ return sys_lgetxattr(path, name, value, size);
+}
+
+static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
+{
+ return sys_fgetxattr(fd, name, value, size);
+}
+
+static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
+{
+ return sys_listxattr(path, list, size);
+}
+
+ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
+{
+ return sys_llistxattr(path, list, size);
+}
+
+ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
+{
+ return sys_flistxattr(fd, list, size);
+}
+
+static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
+{
+ return sys_removexattr(path, name);
+}
+
+static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
+{
+ return sys_lremovexattr(path, name);
+}
+
+static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
+{
+ return sys_fremovexattr(fd, name);
+}
+
+static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ return sys_setxattr(path, name, value, size, flags);
+}
+
+static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+ return sys_lsetxattr(path, name, value, size, flags);
+}
+
+static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
+{
+ return sys_fsetxattr(fd, name, value, size, flags);
+}
+
+static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_read(aiocb);
+}
+
+static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_write(aiocb);
+}
+
+static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_return(aiocb);
+}
+
+static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_cancel(fd, aiocb);
+}
+
+static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_error(aiocb);
+}
+
+static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
+{
+ return sys_aio_fsync(op, aiocb);
+}
+
+static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
+{
+ return sys_aio_suspend(aiocb, n, timeout);
+}
+
+static vfs_op_tuple vfs_default_ops[] = {
+
+ /* Disk operations */
+
+ {SMB_VFS_OP(vfswrap_connect), SMB_VFS_OP_CONNECT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_disconnect), SMB_VFS_OP_DISCONNECT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_statvfs), SMB_VFS_OP_STATVFS,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* Directory operations */
+
+ {SMB_VFS_OP(vfswrap_opendir), SMB_VFS_OP_OPENDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_readdir), SMB_VFS_OP_READDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_seekdir), SMB_VFS_OP_SEEKDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_telldir), SMB_VFS_OP_TELLDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_mkdir), SMB_VFS_OP_MKDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_rmdir), SMB_VFS_OP_RMDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_closedir), SMB_VFS_OP_CLOSEDIR,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* File operations */
+
+ {SMB_VFS_OP(vfswrap_open), SMB_VFS_OP_OPEN,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_close), SMB_VFS_OP_CLOSE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_read), SMB_VFS_OP_READ,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_pread), SMB_VFS_OP_PREAD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_write), SMB_VFS_OP_WRITE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_pwrite), SMB_VFS_OP_PWRITE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lseek), SMB_VFS_OP_LSEEK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sendfile), SMB_VFS_OP_SENDFILE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_rename), SMB_VFS_OP_RENAME,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fsync), SMB_VFS_OP_FSYNC,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_stat), SMB_VFS_OP_STAT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fstat), SMB_VFS_OP_FSTAT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lstat), SMB_VFS_OP_LSTAT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_unlink), SMB_VFS_OP_UNLINK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_chmod), SMB_VFS_OP_CHMOD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fchmod), SMB_VFS_OP_FCHMOD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_chown), SMB_VFS_OP_CHOWN,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fchown), SMB_VFS_OP_FCHOWN,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_chdir), SMB_VFS_OP_CHDIR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_getwd), SMB_VFS_OP_GETWD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_utime), SMB_VFS_OP_UTIME,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lock), SMB_VFS_OP_LOCK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_linux_setlease), SMB_VFS_OP_LINUX_SETLEASE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_getlock), SMB_VFS_OP_GETLOCK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_symlink), SMB_VFS_OP_SYMLINK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_readlink), SMB_VFS_OP_READLINK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_link), SMB_VFS_OP_LINK,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_mknod), SMB_VFS_OP_MKNOD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_realpath), SMB_VFS_OP_REALPATH,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_notify_watch), SMB_VFS_OP_NOTIFY_WATCH,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* NT ACL operations. */
+
+ {SMB_VFS_OP(vfswrap_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_get_nt_acl), SMB_VFS_OP_GET_NT_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_set_nt_acl), SMB_VFS_OP_SET_NT_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* POSIX ACL operations. */
+
+ {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type), SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_permset), SMB_VFS_OP_SYS_ACL_GET_PERMSET,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier), SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_fd), SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_clear_perms), SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_add_perm), SMB_VFS_OP_SYS_ACL_ADD_PERM,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_to_text), SMB_VFS_OP_SYS_ACL_TO_TEXT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_init), SMB_VFS_OP_SYS_ACL_INIT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_create_entry), SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type), SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier), SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_set_permset), SMB_VFS_OP_SYS_ACL_SET_PERMSET,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_valid), SMB_VFS_OP_SYS_ACL_VALID,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_set_fd), SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file), SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_get_perm), SMB_VFS_OP_SYS_ACL_GET_PERM,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_free_acl), SMB_VFS_OP_SYS_ACL_FREE_ACL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier), SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* EA operations. */
+
+ {SMB_VFS_OP(vfswrap_getxattr), SMB_VFS_OP_GETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_llistxattr), SMB_VFS_OP_LLISTXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_flistxattr), SMB_VFS_OP_FLISTXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_removexattr), SMB_VFS_OP_REMOVEXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lremovexattr), SMB_VFS_OP_LREMOVEXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fremovexattr), SMB_VFS_OP_FREMOVEXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_setxattr), SMB_VFS_OP_SETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR,
+ SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(vfswrap_aio_read), SMB_VFS_OP_AIO_READ,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_return), SMB_VFS_OP_AIO_RETURN,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC,
+ SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
+ SMB_VFS_LAYER_OPAQUE},
+
+ /* Finish VFS operations definition */
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_default_init(void);
+NTSTATUS vfs_default_init(void)
+{
+ unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */
+
+ if (ARRAY_SIZE(vfs_default_ops) != needed) {
+ DEBUG(0, ("%s: %u ops registered, but %u ops are required\n",
+ DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed));
+ smb_panic("operation(s) missing from default VFS module");
+ }
+
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+ DEFAULT_VFS_MODULE_NAME, vfs_default_ops);
+}
diff --git a/source/modules/vfs_default_quota.c b/source/modules/vfs_default_quota.c
index 9922a30315d..772c91dc473 100644
--- a/source/modules/vfs_default_quota.c
+++ b/source/modules/vfs_default_quota.c
@@ -92,11 +92,11 @@
#define DEFAULT_QUOTA_GID_NOLIMIT(handle) \
lp_parm_bool(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"gid nolimit",DEFAULT_QUOTA_GID_NOLIMIT_DEFAULT)
-static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+static int default_quota_get_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
{
int ret = -1;
- if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, dq))!=0) {
+ if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, dq))!=0) {
return ret;
}
@@ -122,7 +122,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
unid_t qid;
uint32 qflags = dq->qflags;
qid.uid = DEFAULT_QUOTA_UID(handle);
- SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq);
+ SMB_VFS_NEXT_GET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq);
dq->qflags = qflags;
}
break;
@@ -132,7 +132,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
unid_t qid;
uint32 qflags = dq->qflags;
qid.gid = DEFAULT_QUOTA_GID(handle);
- SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq);
+ SMB_VFS_NEXT_GET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq);
dq->qflags = qflags;
}
break;
@@ -146,7 +146,7 @@ static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct
return ret;
}
-static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+static int default_quota_set_quota(vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
{
int ret = -1;
@@ -179,7 +179,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
break;
}
- if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq))!=0) {
+ if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, dq))!=0) {
return ret;
}
@@ -194,7 +194,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
{
unid_t qid;
qid.uid = DEFAULT_QUOTA_UID(handle);
- ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq);
+ ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_USER_QUOTA_TYPE, qid, dq);
}
break;
#ifdef HAVE_GROUP_QUOTA
@@ -202,7 +202,7 @@ static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct
{
unid_t qid;
qid.gid = DEFAULT_QUOTA_GID(handle);
- ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq);
+ ret = SMB_VFS_NEXT_SET_QUOTA(handle, SMB_GROUP_QUOTA_TYPE, qid, dq);
}
break;
#endif /* HAVE_GROUP_QUOTA */
@@ -224,6 +224,7 @@ static vfs_op_tuple default_quota_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_default_quota_init(void);
NTSTATUS vfs_default_quota_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, DEFAULT_QUOTA_NAME, default_quota_ops);
diff --git a/source/modules/vfs_expand_msdfs.c b/source/modules/vfs_expand_msdfs.c
index d22f6a7f98e..7176c11e4ab 100644
--- a/source/modules/vfs_expand_msdfs.c
+++ b/source/modules/vfs_expand_msdfs.c
@@ -23,6 +23,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
+extern userdom_struct current_user_info;
+
/**********************************************************
Under mapfile we expect a table of the following format:
@@ -135,7 +137,11 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target)
return False;
}
- standard_sub_conn(conn, mapfilename, sizeof(mapfilename));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ mapfilename, sizeof(mapfilename));
DEBUG(10, ("Expanded targethost to %s\n", targethost));
@@ -150,13 +156,12 @@ static BOOL expand_msdfs_target(connection_struct* conn, pstring target)
}
static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, char *buf, size_t bufsiz)
{
pstring target;
int result;
- result = SMB_VFS_NEXT_READLINK(handle, conn, path, target,
+ result = SMB_VFS_NEXT_READLINK(handle, path, target,
sizeof(target));
if (result < 0)
@@ -166,7 +171,7 @@ static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
if ((strncmp(target, "msdfs:", strlen("msdfs:")) == 0) &&
(strchr_m(target, '@') != NULL)) {
- if (!expand_msdfs_target(conn, target)) {
+ if (!expand_msdfs_target(handle->conn, target)) {
errno = ENOENT;
return -1;
}
@@ -184,6 +189,7 @@ static vfs_op_tuple expand_msdfs_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_expand_msdfs_init(void);
NTSTATUS vfs_expand_msdfs_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "expand_msdfs",
diff --git a/source/modules/vfs_extd_audit.c b/source/modules/vfs_extd_audit.c
index cb8c3ffd6ab..06722b3b8c0 100644
--- a/source/modules/vfs_extd_audit.c
+++ b/source/modules/vfs_extd_audit.c
@@ -32,17 +32,17 @@ static int vfs_extd_audit_debug_level = DBGC_VFS;
/* Function prototypes */
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr);
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user);
+static void audit_disconnect(vfs_handle_struct *handle);
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr);
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_rmdir(vfs_handle_struct *handle, const char *path);
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode);
static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname);
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname);
+static int audit_unlink(vfs_handle_struct *handle, const char *path);
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode);
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode);
static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
@@ -123,7 +123,7 @@ static int audit_syslog_priority(vfs_handle_struct *handle)
/* Implementation of vfs_ops. Pass everything on to the default
operation but log event first. */
-static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
+static int audit_connect(vfs_handle_struct *handle, const char *svc, const char *user)
{
int result;
@@ -134,25 +134,25 @@ static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, con
DEBUG(10, ("Connected to service %s as user %s\n",
svc, user));
- result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+ result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
return result;
}
-static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void audit_disconnect(vfs_handle_struct *handle)
{
syslog(audit_syslog_priority(handle), "disconnected\n");
DEBUG(10, ("Disconnected from VFS module extd_audit\n"));
- SMB_VFS_NEXT_DISCONNECT(handle, conn);
+ SMB_VFS_NEXT_DISCONNECT(handle);
return;
}
-static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
{
SMB_STRUCT_DIR *result;
- result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+ result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
fname,
@@ -166,11 +166,11 @@ static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, connection_struc
return result;
}
-static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n",
path,
@@ -184,11 +184,11 @@ static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_rmdir(vfs_handle_struct *handle, const char *path)
{
int result;
- result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+ result = SMB_VFS_NEXT_RMDIR(handle, path);
syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n",
path,
@@ -202,11 +202,11 @@ static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
+static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+ result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n",
fname, result,
@@ -239,11 +239,11 @@ static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
return result;
}
-static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
+static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
{
int result;
- result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+ result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
oldname, newname,
@@ -257,11 +257,11 @@ static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, cons
return result;
}
-static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
+static int audit_unlink(vfs_handle_struct *handle, const char *path)
{
int result;
- result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+ result = SMB_VFS_NEXT_UNLINK(handle, path);
syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
path,
@@ -275,11 +275,11 @@ static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, cons
return result;
}
-static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n",
path, mode,
@@ -293,11 +293,11 @@ static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const
return result;
}
-static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
+static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n",
path, mode,
@@ -347,6 +347,7 @@ static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd
return result;
}
+NTSTATUS vfs_extd_audit_init(void);
NTSTATUS vfs_extd_audit_init(void)
{
NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "extd_audit", audit_op_tuples);
diff --git a/source/modules/vfs_fake_perms.c b/source/modules/vfs_fake_perms.c
index decbe01d3ca..e31adb881c5 100644
--- a/source/modules/vfs_fake_perms.c
+++ b/source/modules/vfs_fake_perms.c
@@ -29,11 +29,11 @@ extern struct current_user current_user;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
-static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
+static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf)
{
int ret = -1;
- ret = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf);
+ ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
if (ret == 0) {
if (S_ISDIR(sbuf->st_mode)) {
sbuf->st_mode = S_IFDIR | S_IRWXU;
@@ -73,6 +73,7 @@ static vfs_op_tuple fake_perms_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_fake_perms_init(void);
NTSTATUS vfs_fake_perms_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_perms", fake_perms_ops);
diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c
index b9ffd6fc05f..6036e49fc15 100644
--- a/source/modules/vfs_full_audit.c
+++ b/source/modules/vfs_full_audit.c
@@ -60,6 +60,8 @@
#include "includes.h"
+extern userdom_struct current_user_info;
+
static int vfs_full_audit_debug_level = DBGC_VFS;
struct vfs_full_audit_private_data {
@@ -72,48 +74,44 @@ struct vfs_full_audit_private_data {
/* Function prototypes */
-static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_connect(vfs_handle_struct *handle,
const char *svc, const char *user);
-static void smb_full_audit_disconnect(vfs_handle_struct *handle,
- connection_struct *conn);
+static void smb_full_audit_disconnect(vfs_handle_struct *handle);
static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
- connection_struct *conn, const char *path,
+ const char *path,
BOOL small_query, SMB_BIG_UINT *bsize,
SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id,
SMB_DISK_QUOTA *qt);
static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id,
SMB_DISK_QUOTA *qt);
static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
struct files_struct *fsp,
SHADOW_COPY_DATA *shadow_copy_data, BOOL labels);
static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path,
struct vfs_statvfs_struct *statbuf);
-static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn,
+static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
const char *fname, const char *mask, uint32 attr);
static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
- connection_struct *conn, SMB_STRUCT_DIR *dirp);
-static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn,
+ SMB_STRUCT_DIR *dirp);
+static void smb_full_audit_seekdir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp, long offset);
-static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn,
+static long smb_full_audit_telldir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp);
-static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_rewinddir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp);
-static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mkdir(vfs_handle_struct *handle,
const char *path, mode_t mode);
-static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rmdir(vfs_handle_struct *handle,
const char *path);
-static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_closedir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp);
-static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn,
- const char *fname, int flags, mode_t mode);
+static int smb_full_audit_open(vfs_handle_struct *handle,
+ const char *fname, files_struct *fsp, int flags, mode_t mode);
static int smb_full_audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
static ssize_t smb_full_audit_read(vfs_handle_struct *handle, files_struct *fsp,
int fd, void *data, size_t n);
@@ -130,46 +128,51 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
files_struct *fsp, int fromfd,
const DATA_BLOB *hdr, SMB_OFF_T offset,
size_t n);
-static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rename(vfs_handle_struct *handle,
const char *oldname, const char *newname);
static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd);
-static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_stat(vfs_handle_struct *handle,
const char *fname, SMB_STRUCT_STAT *sbuf);
static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd,
SMB_STRUCT_STAT *sbuf);
-static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_lstat(vfs_handle_struct *handle,
const char *path, SMB_STRUCT_STAT *sbuf);
-static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_unlink(vfs_handle_struct *handle,
const char *path);
-static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod(vfs_handle_struct *handle,
const char *path, mode_t mode);
static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd,
mode_t mode);
-static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chown(vfs_handle_struct *handle,
const char *path, uid_t uid, gid_t gid);
static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd,
uid_t uid, gid_t gid);
-static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chdir(vfs_handle_struct *handle,
const char *path);
-static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_getwd(vfs_handle_struct *handle,
char *path);
-static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_utime(vfs_handle_struct *handle,
const char *path, struct utimbuf *times);
static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
int fd, SMB_OFF_T len);
static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int fd,
int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
+static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp, int fd,
+ uint32 share_mode);
+static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, int leasetype);
static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd,
SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
-static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_symlink(vfs_handle_struct *handle,
const char *oldpath, const char *newpath);
-static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_readlink(vfs_handle_struct *handle,
const char *path, char *buf, size_t bufsiz);
-static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_link(vfs_handle_struct *handle,
const char *oldpath, const char *newpath);
-static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mknod(vfs_handle_struct *handle,
const char *pathname, mode_t mode, SMB_DEV_T dev);
-static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_realpath(vfs_handle_struct *handle,
const char *path, char *resolved_path);
static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
int fd, uint32 security_info,
@@ -183,120 +186,99 @@ static BOOL smb_full_audit_fset_nt_acl(vfs_handle_struct *handle, files_struct *
static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
const char *name, uint32 security_info_sent,
SEC_DESC *psd);
-static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod_acl(vfs_handle_struct *handle,
const char *path, mode_t mode);
static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp,
int fd, mode_t mode);
static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_T theacl, int entry_id,
SMB_ACL_ENTRY_T *entry_p);
static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry_d,
SMB_ACL_TAG_T *tag_type_p);
static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry_d,
SMB_ACL_PERMSET_T *permset_p);
static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry_d);
static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle,
- connection_struct *conn,
const char *path_p,
SMB_ACL_TYPE_T type);
static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle,
files_struct *fsp,
int fd);
static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_PERMSET_T permset);
static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_PERMSET_T permset,
SMB_ACL_PERM_T perm);
static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
- connection_struct *conn, SMB_ACL_T theacl,
+ SMB_ACL_T theacl,
ssize_t *plen);
static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
- connection_struct *conn,
int count);
static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
- connection_struct *conn, SMB_ACL_T *pacl,
+ SMB_ACL_T *pacl,
SMB_ACL_ENTRY_T *pentry);
static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry,
SMB_ACL_TAG_T tagtype);
static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry,
void *qual);
static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_ENTRY_T entry,
SMB_ACL_PERMSET_T permset);
static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_T theacl );
static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle,
- connection_struct *conn,
const char *name, SMB_ACL_TYPE_T acltype,
SMB_ACL_T theacl);
static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp,
int fd, SMB_ACL_T theacl);
static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
- connection_struct *conn,
const char *path);
static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_PERMSET_T permset,
SMB_ACL_PERM_T perm);
static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
- connection_struct *conn,
char *text);
static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
- connection_struct *conn,
SMB_ACL_T posix_acl);
static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
void *qualifier,
SMB_ACL_TAG_T tagtype);
static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, void *value, size_t size);
static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, const char *name,
void *value, size_t size);
static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd,
const char *name, void *value, size_t size);
static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, char *list, size_t size);
static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, char *list, size_t size);
static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd, char *list,
size_t size);
static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name);
static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name);
static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd,
const char *name);
static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, const void *value, size_t size,
int flags);
static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, const void *value, size_t size,
int flags);
static int smb_full_audit_fsetxattr(struct vfs_handle_struct *handle,
@@ -399,6 +381,10 @@ static vfs_op_tuple audit_op_tuples[] = {
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_lock), SMB_VFS_OP_LOCK,
SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_kernel_flock), SMB_VFS_OP_KERNEL_FLOCK,
+ SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_linux_setlease), SMB_VFS_OP_LINUX_SETLEASE,
+ SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_getlock), SMB_VFS_OP_GETLOCK,
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_symlink), SMB_VFS_OP_SYMLINK,
@@ -566,6 +552,8 @@ static struct {
{ SMB_VFS_OP_UTIME, "utime" },
{ SMB_VFS_OP_FTRUNCATE, "ftruncate" },
{ SMB_VFS_OP_LOCK, "lock" },
+ { SMB_VFS_OP_KERNEL_FLOCK, "kernel_flock" },
+ { SMB_VFS_OP_LINUX_SETLEASE, "linux_setlease" },
{ SMB_VFS_OP_GETLOCK, "getlock" },
{ SMB_VFS_OP_SYMLINK, "symlink" },
{ SMB_VFS_OP_READLINK, "readlink" },
@@ -669,7 +657,11 @@ static char *audit_prefix(connection_struct *conn)
pstrcpy(prefix, lp_parm_const_string(SNUM(conn), "full_audit",
"prefix", "%u|%I"));
- standard_sub_snum(SNUM(conn), prefix, sizeof(prefix)-1);
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ prefix, sizeof(prefix));
return prefix;
}
@@ -811,7 +803,7 @@ static void free_private_data(void **p_data)
/* Implementation of vfs_ops. Pass everything on to the default
operation but log event first. */
-static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_connect(vfs_handle_struct *handle,
const char *svc, const char *user)
{
int result;
@@ -832,17 +824,17 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *
openlog("smbd_audit", 0, audit_syslog_facility(handle));
init_bitmap(&pd->success_ops,
- lp_parm_string_list(SNUM(conn), "full_audit", "success",
+ lp_parm_string_list(SNUM(handle->conn), "full_audit", "success",
none));
init_bitmap(&pd->failure_ops,
- lp_parm_string_list(SNUM(conn), "full_audit", "failure",
+ lp_parm_string_list(SNUM(handle->conn), "full_audit", "failure",
all));
/* Store the private data. */
SMB_VFS_HANDLE_SET_DATA(handle, pd, free_private_data,
struct vfs_full_audit_private_data, return -1);
- result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
+ result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
do_log(SMB_VFS_OP_CONNECT, True, handle,
"%s", svc);
@@ -850,13 +842,12 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *
return result;
}
-static void smb_full_audit_disconnect(vfs_handle_struct *handle,
- connection_struct *conn)
+static void smb_full_audit_disconnect(vfs_handle_struct *handle)
{
- SMB_VFS_NEXT_DISCONNECT(handle, conn);
+ SMB_VFS_NEXT_DISCONNECT(handle);
do_log(SMB_VFS_OP_DISCONNECT, True, handle,
- "%s", lp_servicename(SNUM(conn)));
+ "%s", lp_servicename(SNUM(handle->conn)));
/* The bitmaps will be disconnected when the private
data is deleted. */
@@ -865,13 +856,13 @@ static void smb_full_audit_disconnect(vfs_handle_struct *handle,
}
static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
- connection_struct *conn, const char *path,
+ const char *path,
BOOL small_query, SMB_BIG_UINT *bsize,
SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
SMB_BIG_UINT result;
- result = SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize,
+ result = SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize,
dfree, dsize);
/* Don't have a reasonable notion of failure here */
@@ -882,13 +873,12 @@ static SMB_BIG_UINT smb_full_audit_disk_free(vfs_handle_struct *handle,
}
static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id,
SMB_DISK_QUOTA *qt)
{
int result;
- result = SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt);
+ result = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt);
do_log(SMB_VFS_OP_GET_QUOTA, (result >= 0), handle, "");
@@ -897,13 +887,12 @@ static int smb_full_audit_get_quota(struct vfs_handle_struct *handle,
static int smb_full_audit_set_quota(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id,
SMB_DISK_QUOTA *qt)
{
int result;
- result = SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt);
+ result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt);
do_log(SMB_VFS_OP_SET_QUOTA, (result >= 0), handle, "");
@@ -924,25 +913,24 @@ static int smb_full_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
}
static int smb_full_audit_statvfs(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path,
struct vfs_statvfs_struct *statbuf)
{
int result;
- result = SMB_VFS_NEXT_STATVFS(handle, conn, path, statbuf);
+ result = SMB_VFS_NEXT_STATVFS(handle, path, statbuf);
do_log(SMB_VFS_OP_STATVFS, (result >= 0), handle, "");
return result;
}
-static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connection_struct *conn,
+static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle,
const char *fname, const char *mask, uint32 attr)
{
SMB_STRUCT_DIR *result;
- result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+ result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
do_log(SMB_VFS_OP_OPENDIR, (result != NULL), handle, "%s", fname);
@@ -950,11 +938,11 @@ static SMB_STRUCT_DIR *smb_full_audit_opendir(vfs_handle_struct *handle, connect
}
static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
- connection_struct *conn, SMB_STRUCT_DIR *dirp)
+ SMB_STRUCT_DIR *dirp)
{
SMB_STRUCT_DIRENT *result;
- result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
+ result = SMB_VFS_NEXT_READDIR(handle, dirp);
/* This operation has no reasonable error condition
* (End of dir is also failure), so always succeed.
@@ -964,78 +952,78 @@ static SMB_STRUCT_DIRENT *smb_full_audit_readdir(vfs_handle_struct *handle,
return result;
}
-static void smb_full_audit_seekdir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_seekdir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp, long offset)
{
- SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp, offset);
+ SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset);
do_log(SMB_VFS_OP_SEEKDIR, True, handle, "");
return;
}
-static long smb_full_audit_telldir(vfs_handle_struct *handle, connection_struct *conn,
+static long smb_full_audit_telldir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp)
{
long result;
- result = SMB_VFS_NEXT_TELLDIR(handle, conn, dirp);
+ result = SMB_VFS_NEXT_TELLDIR(handle, dirp);
do_log(SMB_VFS_OP_TELLDIR, True, handle, "");
return result;
}
-static void smb_full_audit_rewinddir(vfs_handle_struct *handle, connection_struct *conn,
+static void smb_full_audit_rewinddir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp)
{
- SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp);
+ SMB_VFS_NEXT_REWINDDIR(handle, dirp);
do_log(SMB_VFS_OP_REWINDDIR, True, handle, "");
return;
}
-static int smb_full_audit_mkdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mkdir(vfs_handle_struct *handle,
const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
do_log(SMB_VFS_OP_MKDIR, (result >= 0), handle, "%s", path);
return result;
}
-static int smb_full_audit_rmdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rmdir(vfs_handle_struct *handle,
const char *path)
{
int result;
- result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
+ result = SMB_VFS_NEXT_RMDIR(handle, path);
do_log(SMB_VFS_OP_RMDIR, (result >= 0), handle, "%s", path);
return result;
}
-static int smb_full_audit_closedir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_closedir(vfs_handle_struct *handle,
SMB_STRUCT_DIR *dirp)
{
int result;
- result = SMB_VFS_NEXT_CLOSEDIR(handle, conn, dirp);
+ result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
do_log(SMB_VFS_OP_CLOSEDIR, (result >= 0), handle, "");
return result;
}
-static int smb_full_audit_open(vfs_handle_struct *handle, connection_struct *conn,
- const char *fname, int flags, mode_t mode)
+static int smb_full_audit_open(vfs_handle_struct *handle,
+ const char *fname, files_struct *fsp, int flags, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
+ result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s",
((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r",
@@ -1133,12 +1121,12 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
return result;
}
-static int smb_full_audit_rename(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_rename(vfs_handle_struct *handle,
const char *oldname, const char *newname)
{
int result;
- result = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+ result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
do_log(SMB_VFS_OP_RENAME, (result >= 0), handle, "%s|%s", oldname, newname);
@@ -1156,12 +1144,12 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, in
return result;
}
-static int smb_full_audit_stat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_stat(vfs_handle_struct *handle,
const char *fname, SMB_STRUCT_STAT *sbuf)
{
int result;
- result = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf);
+ result = SMB_VFS_NEXT_STAT(handle, fname, sbuf);
do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", fname);
@@ -1180,36 +1168,36 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, in
return result;
}
-static int smb_full_audit_lstat(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_lstat(vfs_handle_struct *handle,
const char *path, SMB_STRUCT_STAT *sbuf)
{
int result;
- result = SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf);
+ result = SMB_VFS_NEXT_LSTAT(handle, path, sbuf);
do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", path);
return result;
}
-static int smb_full_audit_unlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_unlink(vfs_handle_struct *handle,
const char *path)
{
int result;
- result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+ result = SMB_VFS_NEXT_UNLINK(handle, path);
do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", path);
return result;
}
-static int smb_full_audit_chmod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod(vfs_handle_struct *handle,
const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
do_log(SMB_VFS_OP_CHMOD, (result >= 0), handle, "%s|%o", path, mode);
@@ -1229,12 +1217,12 @@ static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, i
return result;
}
-static int smb_full_audit_chown(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chown(vfs_handle_struct *handle,
const char *path, uid_t uid, gid_t gid)
{
int result;
- result = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid);
+ result = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
do_log(SMB_VFS_OP_CHOWN, (result >= 0), handle, "%s|%ld|%ld",
path, (long int)uid, (long int)gid);
@@ -1255,36 +1243,36 @@ static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, i
return result;
}
-static int smb_full_audit_chdir(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chdir(vfs_handle_struct *handle,
const char *path)
{
int result;
- result = SMB_VFS_NEXT_CHDIR(handle, conn, path);
+ result = SMB_VFS_NEXT_CHDIR(handle, path);
do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s", path);
return result;
}
-static char *smb_full_audit_getwd(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_getwd(vfs_handle_struct *handle,
char *path)
{
char *result;
- result = SMB_VFS_NEXT_GETWD(handle, conn, path);
+ result = SMB_VFS_NEXT_GETWD(handle, path);
do_log(SMB_VFS_OP_GETWD, (result != NULL), handle, "%s", path);
return result;
}
-static int smb_full_audit_utime(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_utime(vfs_handle_struct *handle,
const char *path, struct utimbuf *times)
{
int result;
- result = SMB_VFS_NEXT_UTIME(handle, conn, path, times);
+ result = SMB_VFS_NEXT_UTIME(handle, path, times);
do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path);
@@ -1316,6 +1304,33 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in
return result;
}
+static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle,
+ struct files_struct *fsp, int fd,
+ uint32 share_mode)
+{
+ int result;
+
+ result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode);
+
+ do_log(SMB_VFS_OP_KERNEL_FLOCK, (result >= 0), handle, "%s",
+ fsp->fsp_name);
+
+ return result;
+}
+
+static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, int leasetype)
+{
+ int result;
+
+ result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, fd, leasetype);
+
+ do_log(SMB_VFS_OP_LINUX_SETLEASE, (result >= 0), handle, "%s",
+ fsp->fsp_name);
+
+ return result;
+}
+
static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd,
SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
{
@@ -1328,12 +1343,12 @@ static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp,
return result;
}
-static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_symlink(vfs_handle_struct *handle,
const char *oldpath, const char *newpath)
{
int result;
- result = SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
+ result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
do_log(SMB_VFS_OP_SYMLINK, (result >= 0), handle,
"%s|%s", oldpath, newpath);
@@ -1341,24 +1356,24 @@ static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *
return result;
}
-static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_readlink(vfs_handle_struct *handle,
const char *path, char *buf, size_t bufsiz)
{
int result;
- result = SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
+ result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", path);
return result;
}
-static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_link(vfs_handle_struct *handle,
const char *oldpath, const char *newpath)
{
int result;
- result = SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
+ result = SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
do_log(SMB_VFS_OP_LINK, (result >= 0), handle,
"%s|%s", oldpath, newpath);
@@ -1366,24 +1381,24 @@ static int smb_full_audit_link(vfs_handle_struct *handle, connection_struct *con
return result;
}
-static int smb_full_audit_mknod(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_mknod(vfs_handle_struct *handle,
const char *pathname, mode_t mode, SMB_DEV_T dev)
{
int result;
- result = SMB_VFS_NEXT_MKNOD(handle, conn, pathname, mode, dev);
+ result = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev);
do_log(SMB_VFS_OP_MKNOD, (result >= 0), handle, "%s", pathname);
return result;
}
-static char *smb_full_audit_realpath(vfs_handle_struct *handle, connection_struct *conn,
+static char *smb_full_audit_realpath(vfs_handle_struct *handle,
const char *path, char *resolved_path)
{
char *result;
- result = SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
+ result = SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path);
@@ -1448,12 +1463,12 @@ static BOOL smb_full_audit_set_nt_acl(vfs_handle_struct *handle, files_struct *f
return result;
}
-static int smb_full_audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn,
+static int smb_full_audit_chmod_acl(vfs_handle_struct *handle,
const char *path, mode_t mode)
{
int result;
- result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
+ result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
do_log(SMB_VFS_OP_CHMOD_ACL, (result >= 0), handle,
"%s|%o", path, mode);
@@ -1475,13 +1490,13 @@ static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fs
}
static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_T theacl, int entry_id,
SMB_ACL_ENTRY_T *entry_p)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id,
+ result = SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, theacl, entry_id,
entry_p);
do_log(SMB_VFS_OP_SYS_ACL_GET_ENTRY, (result >= 0), handle,
@@ -1491,13 +1506,13 @@ static int smb_full_audit_sys_acl_get_entry(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry_d,
SMB_ACL_TAG_T *tag_type_p)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d,
+ result = SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, entry_d,
tag_type_p);
do_log(SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, (result >= 0), handle,
@@ -1507,13 +1522,13 @@ static int smb_full_audit_sys_acl_get_tag_type(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry_d,
SMB_ACL_PERMSET_T *permset_p)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d,
+ result = SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, entry_d,
permset_p);
do_log(SMB_VFS_OP_SYS_ACL_GET_PERMSET, (result >= 0), handle,
@@ -1523,12 +1538,12 @@ static int smb_full_audit_sys_acl_get_permset(vfs_handle_struct *handle,
}
static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry_d)
{
void *result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d);
+ result = SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, entry_d);
do_log(SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, (result != NULL), handle,
"");
@@ -1537,13 +1552,12 @@ static void * smb_full_audit_sys_acl_get_qualifier(vfs_handle_struct *handle,
}
static SMB_ACL_T smb_full_audit_sys_acl_get_file(vfs_handle_struct *handle,
- connection_struct *conn,
const char *path_p,
SMB_ACL_TYPE_T type)
{
SMB_ACL_T result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type);
+ result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type);
do_log(SMB_VFS_OP_SYS_ACL_GET_FILE, (result != NULL), handle,
"%s", path_p);
@@ -1565,12 +1579,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_PERMSET_T permset)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset);
+ result = SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, permset);
do_log(SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, (result >= 0), handle,
"");
@@ -1579,13 +1593,13 @@ static int smb_full_audit_sys_acl_clear_perms(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_PERMSET_T permset,
SMB_ACL_PERM_T perm)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm);
+ result = SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, permset, perm);
do_log(SMB_VFS_OP_SYS_ACL_ADD_PERM, (result >= 0), handle,
"");
@@ -1594,12 +1608,12 @@ static int smb_full_audit_sys_acl_add_perm(vfs_handle_struct *handle,
}
static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
- connection_struct *conn, SMB_ACL_T theacl,
+ SMB_ACL_T theacl,
ssize_t *plen)
{
char * result;
- result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen);
+ result = SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, theacl, plen);
do_log(SMB_VFS_OP_SYS_ACL_TO_TEXT, (result != NULL), handle,
"");
@@ -1608,12 +1622,12 @@ static char * smb_full_audit_sys_acl_to_text(vfs_handle_struct *handle,
}
static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
- connection_struct *conn,
+
int count)
{
SMB_ACL_T result;
- result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count);
+ result = SMB_VFS_NEXT_SYS_ACL_INIT(handle, count);
do_log(SMB_VFS_OP_SYS_ACL_INIT, (result != NULL), handle,
"");
@@ -1622,12 +1636,12 @@ static SMB_ACL_T smb_full_audit_sys_acl_init(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
- connection_struct *conn, SMB_ACL_T *pacl,
+ SMB_ACL_T *pacl,
SMB_ACL_ENTRY_T *pentry)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry);
+ result = SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, pacl, pentry);
do_log(SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, (result >= 0), handle,
"");
@@ -1636,13 +1650,13 @@ static int smb_full_audit_sys_acl_create_entry(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry,
SMB_ACL_TAG_T tagtype)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry,
+ result = SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, entry,
tagtype);
do_log(SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, (result >= 0), handle,
@@ -1652,13 +1666,13 @@ static int smb_full_audit_sys_acl_set_tag_type(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry,
void *qual)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual);
+ result = SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, entry, qual);
do_log(SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, (result >= 0), handle,
"");
@@ -1667,13 +1681,13 @@ static int smb_full_audit_sys_acl_set_qualifier(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_ENTRY_T entry,
SMB_ACL_PERMSET_T permset)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset);
+ result = SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, entry, permset);
do_log(SMB_VFS_OP_SYS_ACL_SET_PERMSET, (result >= 0), handle,
"");
@@ -1682,12 +1696,12 @@ static int smb_full_audit_sys_acl_set_permset(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_T theacl )
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl);
+ result = SMB_VFS_NEXT_SYS_ACL_VALID(handle, theacl);
do_log(SMB_VFS_OP_SYS_ACL_VALID, (result >= 0), handle,
"");
@@ -1696,13 +1710,13 @@ static int smb_full_audit_sys_acl_valid(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_set_file(vfs_handle_struct *handle,
- connection_struct *conn,
+
const char *name, SMB_ACL_TYPE_T acltype,
SMB_ACL_T theacl)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype,
+ result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype,
theacl);
do_log(SMB_VFS_OP_SYS_ACL_SET_FILE, (result >= 0), handle,
@@ -1725,12 +1739,12 @@ static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct
}
static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
- connection_struct *conn,
+
const char *path)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path);
+ result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path);
do_log(SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, (result >= 0), handle,
"%s", path);
@@ -1739,13 +1753,13 @@ static int smb_full_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_PERMSET_T permset,
SMB_ACL_PERM_T perm)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm);
+ result = SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, permset, perm);
do_log(SMB_VFS_OP_SYS_ACL_GET_PERM, (result >= 0), handle,
"");
@@ -1754,12 +1768,12 @@ static int smb_full_audit_sys_acl_get_perm(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
- connection_struct *conn,
+
char *text)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text);
+ result = SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, text);
do_log(SMB_VFS_OP_SYS_ACL_FREE_TEXT, (result >= 0), handle,
"");
@@ -1768,12 +1782,12 @@ static int smb_full_audit_sys_acl_free_text(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
- connection_struct *conn,
+
SMB_ACL_T posix_acl)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl);
+ result = SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, posix_acl);
do_log(SMB_VFS_OP_SYS_ACL_FREE_ACL, (result >= 0), handle,
"");
@@ -1782,13 +1796,12 @@ static int smb_full_audit_sys_acl_free_acl(vfs_handle_struct *handle,
}
static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
- connection_struct *conn,
void *qualifier,
SMB_ACL_TAG_T tagtype)
{
int result;
- result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier,
+ result = SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, qualifier,
tagtype);
do_log(SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, (result >= 0), handle,
@@ -1798,12 +1811,12 @@ static int smb_full_audit_sys_acl_free_qualifier(vfs_handle_struct *handle,
}
static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, void *value, size_t size)
{
ssize_t result;
- result = SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size);
+ result = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, size);
do_log(SMB_VFS_OP_GETXATTR, (result >= 0), handle,
"%s|%s", path, name);
@@ -1812,13 +1825,12 @@ static ssize_t smb_full_audit_getxattr(struct vfs_handle_struct *handle,
}
static ssize_t smb_full_audit_lgetxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, const char *name,
void *value, size_t size)
{
ssize_t result;
- result = SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size);
+ result = SMB_VFS_NEXT_LGETXATTR(handle, path, name, value, size);
do_log(SMB_VFS_OP_LGETXATTR, (result >= 0), handle,
"%s|%s", path, name);
@@ -1841,12 +1853,11 @@ static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle,
}
static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, char *list, size_t size)
{
ssize_t result;
- result = SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size);
+ result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size);
do_log(SMB_VFS_OP_LISTXATTR, (result >= 0), handle, "%s", path);
@@ -1854,12 +1865,11 @@ static ssize_t smb_full_audit_listxattr(struct vfs_handle_struct *handle,
}
static ssize_t smb_full_audit_llistxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn,
const char *path, char *list, size_t size)
{
ssize_t result;
- result = SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size);
+ result = SMB_VFS_NEXT_LLISTXATTR(handle, path, list, size);
do_log(SMB_VFS_OP_LLISTXATTR, (result >= 0), handle, "%s", path);
@@ -1881,12 +1891,12 @@ static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle,
}
static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name)
{
int result;
- result = SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name);
+ result = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
do_log(SMB_VFS_OP_REMOVEXATTR, (result >= 0), handle,
"%s|%s", path, name);
@@ -1895,12 +1905,12 @@ static int smb_full_audit_removexattr(struct vfs_handle_struct *handle,
}
static int smb_full_audit_lremovexattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name)
{
int result;
- result = SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name);
+ result = SMB_VFS_NEXT_LREMOVEXATTR(handle, path, name);
do_log(SMB_VFS_OP_LREMOVEXATTR, (result >= 0), handle,
"%s|%s", path, name);
@@ -1923,13 +1933,13 @@ static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle,
}
static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, const void *value, size_t size,
int flags)
{
int result;
- result = SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size,
+ result = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, size,
flags);
do_log(SMB_VFS_OP_SETXATTR, (result >= 0), handle,
@@ -1939,13 +1949,13 @@ static int smb_full_audit_setxattr(struct vfs_handle_struct *handle,
}
static int smb_full_audit_lsetxattr(struct vfs_handle_struct *handle,
- struct connection_struct *conn, const char *path,
+ const char *path,
const char *name, const void *value, size_t size,
int flags)
{
int result;
- result = SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size,
+ result = SMB_VFS_NEXT_LSETXATTR(handle, path, name, value, size,
flags);
do_log(SMB_VFS_OP_LSETXATTR, (result >= 0), handle,
@@ -2047,6 +2057,7 @@ static int smb_full_audit_aio_suspend(struct vfs_handle_struct *handle, struct f
}
+NTSTATUS vfs_full_audit_init(void);
NTSTATUS vfs_full_audit_init(void)
{
NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
diff --git a/source/modules/vfs_gpfs.c b/source/modules/vfs_gpfs.c
new file mode 100644
index 00000000000..20c9f56a170
--- /dev/null
+++ b/source/modules/vfs_gpfs.c
@@ -0,0 +1,674 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap gpfs calls in vfs functions.
+
+ Copyright (C) Christian Ambach <cambach1@de.ibm.com> 2006
+
+ Major code contributions by Chetan Shringarpure <chetan.sh@in.ibm.com>
+ and Gomati Mohanan <gomati.mohanan@in.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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+#include <gpfs_gpl.h>
+#include "nfs4_acls.h"
+
+
+static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, uint32 share_mode)
+{
+
+ START_PROFILE(syscall_kernel_flock);
+
+ kernel_flock(fsp->fh->fd, share_mode);
+
+ if (!set_gpfs_sharemode(fsp, fsp->access_mask, fsp->share_access)) {
+
+ return -1;
+
+ }
+
+ END_PROFILE(syscall_kernel_flock);
+
+ return 0;
+}
+
+static int vfs_gpfs_setlease(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, int leasetype)
+{
+ int ret;
+
+ START_PROFILE(syscall_linux_setlease);
+
+ if ( linux_set_lease_sighandler(fd) == -1)
+ return -1;
+
+ ret = set_gpfs_lease(fd,leasetype);
+
+ if ( ret < 0 ) {
+ /* This must have come from GPFS not being available */
+ /* or some other error, hence call the default */
+ ret = linux_setlease(fd, leasetype);
+ }
+
+ END_PROFILE(syscall_linux_setlease);
+
+ return ret;
+}
+
+
+
+static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
+{
+ int i;
+ if (gacl==NULL)
+ {
+ DEBUG(0, ("gpfs acl is NULL\n"));
+ return;
+ }
+
+ DEBUG(level, ("gpfs acl: nace: %d, type:%d, version:%d, level:%d, len:%d\n",
+ gacl->acl_nace, gacl->acl_type, gacl->acl_version, gacl->acl_level, gacl->acl_len));
+ for(i=0; i<gacl->acl_nace; i++)
+ {
+ struct gpfs_ace_v4 *gace = gacl->ace_v4 + i;
+ DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, iflags:0x%x, who:%u\n",
+ i, gace->aceType, gace->aceFlags, gace->aceMask,
+ gace->aceIFlags, gace->aceWho));
+ }
+}
+
+static struct gpfs_acl *gpfs_getacl_alloc(const char *fname, gpfs_aclType_t type)
+{
+ struct gpfs_acl *acl;
+ size_t len = 200;
+ int ret;
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+
+ acl = (struct gpfs_acl *)talloc_size(mem_ctx, len);
+ if (acl == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ acl->acl_len = len;
+ acl->acl_level = 0;
+ acl->acl_version = 0;
+ acl->acl_type = type;
+
+ ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
+ if ((ret != 0) && (errno == ENOSPC)) {
+ struct gpfs_acl *new_acl = (struct gpfs_acl *)talloc_size(
+ mem_ctx, acl->acl_len + sizeof(struct gpfs_acl));
+ if (new_acl == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ new_acl->acl_len = acl->acl_len;
+ new_acl->acl_level = acl->acl_level;
+ new_acl->acl_version = acl->acl_version;
+ new_acl->acl_type = acl->acl_type;
+ acl = new_acl;
+
+ ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
+ }
+ if (ret != 0)
+ {
+ DEBUG(8, ("smbd_gpfs_getacl failed with %s\n",strerror(errno)));
+ return NULL;
+ }
+
+ return acl;
+}
+
+static BOOL gpfs_get_nfs4_acl(struct files_struct *fsp, SMB4ACL_T **ppacl, BOOL *pretryPosix)
+{
+ TALLOC_CTX *mem_ctx;
+ int i;
+ struct gpfs_acl *gacl = NULL;
+
+ mem_ctx = main_loop_talloc_get();
+
+ DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fsp->fsp_name));
+
+ /* First get the real acl length */
+ gacl = gpfs_getacl_alloc(fsp->fsp_name, GPFS_ACL_TYPE_NFS4);
+ if (gacl == NULL) {
+ DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
+ fsp->fsp_name, strerror(errno)));
+ return False;
+ }
+
+ if (gacl->acl_type != GPFS_ACL_TYPE_NFS4) {
+ DEBUG(10, ("Got non-nfsv4 acl\n"));
+ *pretryPosix = True;
+ return False;
+ }
+
+ *ppacl = smb_create_smb4acl();
+
+ DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
+ gacl->acl_len, gacl->acl_level, gacl->acl_version,
+ gacl->acl_nace));
+
+ for (i=0; i<gacl->acl_nace; i++) {
+ struct gpfs_ace_v4 *gace = &gacl->ace_v4[i];
+ SMB_ACE4PROP_T smbace;
+ memset(&smbace, 0, sizeof(SMB4ACE_T));
+
+ DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
+ "who: %d\n", gace->aceType, gace->aceIFlags,
+ gace->aceFlags, gace->aceMask, gace->aceWho));
+
+ if (gace->aceIFlags & ACE4_IFLAG_SPECIAL_ID) {
+ smbace.flags |= SMB_ACE4_ID_SPECIAL;
+ switch (gace->aceWho) {
+ case ACE4_SPECIAL_OWNER:
+ smbace.who.special_id = SMB_ACE4_WHO_OWNER;
+ break;
+ case ACE4_SPECIAL_GROUP:
+ smbace.who.special_id = SMB_ACE4_WHO_GROUP;
+ break;
+ case ACE4_SPECIAL_EVERYONE:
+ smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
+ break;
+ default:
+ DEBUG(8, ("invalid special gpfs id %d "
+ "ignored\n", gace->aceWho));
+ continue; /* don't add it */
+ }
+ } else {
+ if (gace->aceFlags & ACE4_FLAG_GROUP_ID)
+ smbace.who.gid = gace->aceWho;
+ else
+ smbace.who.uid = gace->aceWho;
+ }
+
+ smbace.aceType = gace->aceType;
+ smbace.aceFlags = gace->aceFlags;
+ smbace.aceMask = gace->aceMask;
+ smbace.flags = (gace->aceIFlags&ACE4_IFLAG_SPECIAL_ID) ? SMB_ACE4_ID_SPECIAL : 0;
+
+ smb_add_ace4(*ppacl, &smbace);
+ }
+
+ return True;
+}
+
+static size_t gpfsacl_get_nt_acl_common(files_struct *fsp,
+ uint32 security_info, SEC_DESC **ppdesc)
+{
+ SMB4ACL_T *pacl = NULL;
+ BOOL result;
+ BOOL retryPosix = False;
+
+ *ppdesc = NULL;
+ result = gpfs_get_nfs4_acl(fsp, &pacl, &retryPosix);
+ if (retryPosix)
+ {
+ DEBUG(10, ("retrying with posix acl...\n"));
+ return get_nt_acl(fsp, security_info, ppdesc);
+ }
+ if (result==False)
+ return 0;
+
+ return smb_get_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
+}
+
+size_t gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
+ files_struct *fsp, int fd, uint32 security_info,
+ SEC_DESC **ppdesc)
+{
+ return gpfsacl_get_nt_acl_common(fsp, security_info, ppdesc);
+}
+
+size_t gpfsacl_get_nt_acl(vfs_handle_struct *handle,
+ files_struct *fsp, const char *name,
+ uint32 security_info, SEC_DESC **ppdesc)
+{
+ return gpfsacl_get_nt_acl_common(fsp, security_info, ppdesc);
+}
+
+static BOOL gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
+{
+ int ret;
+ gpfs_aclLen_t gacl_len;
+ SMB4ACE_T *smbace;
+ struct gpfs_acl *gacl;
+ TALLOC_CTX *mem_ctx = main_loop_talloc_get();
+
+ gacl_len = sizeof(struct gpfs_acl) +
+ (smb_get_naces(smbacl)-1)*sizeof(gpfs_ace_v4_t);
+
+ gacl = talloc_size(mem_ctx, gacl_len);
+ if (gacl == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ errno = ENOMEM;
+ return False;
+ }
+
+ gacl->acl_len = gacl_len;
+ gacl->acl_level = 0;
+ gacl->acl_version = GPFS_ACL_VERSION_NFS4;
+ gacl->acl_type = GPFS_ACL_TYPE_NFS4;
+ gacl->acl_nace = 0; /* change later... */
+
+ for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
+ struct gpfs_ace_v4 *gace = &gacl->ace_v4[gacl->acl_nace];
+ SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
+
+ gace->aceType = aceprop->aceType;
+ gace->aceFlags = aceprop->aceFlags;
+ gace->aceMask = aceprop->aceMask;
+ gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0;
+
+ if (aceprop->flags&SMB_ACE4_ID_SPECIAL)
+ {
+ switch(aceprop->who.special_id)
+ {
+ case SMB_ACE4_WHO_EVERYONE:
+ gace->aceWho = ACE4_SPECIAL_EVERYONE;
+ break;
+ case SMB_ACE4_WHO_OWNER:
+ gace->aceWho = ACE4_SPECIAL_OWNER;
+ break;
+ case SMB_ACE4_WHO_GROUP:
+ gace->aceWho = ACE4_SPECIAL_GROUP;
+ break;
+ default:
+ DEBUG(8, ("unsupported special_id %d\n", aceprop->who.special_id));
+ continue; /* don't add it !!! */
+ }
+ } else {
+ /* just only for the type safety... */
+ if (aceprop->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)
+ gace->aceWho = aceprop->who.gid;
+ else
+ gace->aceWho = aceprop->who.uid;
+ }
+
+ gacl->acl_nace++;
+ }
+
+ ret = smbd_gpfs_putacl(fsp->fsp_name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl);
+ if (ret != 0) {
+ DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno)));
+ gpfs_dumpacl(8, gacl);
+ return False;
+ }
+
+ DEBUG(10, ("gpfs_putacl succeeded\n"));
+ return True;
+}
+
+static BOOL gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
+{
+ struct gpfs_acl *acl;
+ BOOL result = False;
+
+ acl = gpfs_getacl_alloc(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
+ if (acl == NULL)
+ return False;
+
+ if (acl->acl_version&GPFS_ACL_VERSION_NFS4)
+ {
+ result = smb_set_nt_acl_nfs4(
+ fsp, security_info_sent, psd,
+ gpfsacl_process_smbacl);
+ } else { /* assume POSIX ACL - by default... */
+ result = set_nt_acl(fsp, security_info_sent, psd);
+ }
+
+ return result;
+}
+
+static BOOL gpfsacl_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
+{
+ return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
+}
+
+static BOOL gpfsacl_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, char *name, uint32 security_info_sent, SEC_DESC *psd)
+{
+ return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
+}
+
+static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl)
+{
+ SMB_ACL_T result;
+ int i;
+
+ result = sys_acl_init(pacl->acl_nace);
+ if (result == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ result->count = pacl->acl_nace;
+
+ for (i=0; i<pacl->acl_nace; i++) {
+ struct smb_acl_entry *ace = &result->acl[i];
+ const struct gpfs_ace_v1 *g_ace = &pacl->ace_v1[i];
+
+ DEBUG(10, ("Converting type %d id %lu perm %x\n",
+ (int)g_ace->ace_type, (unsigned long)g_ace->ace_who,
+ (int)g_ace->ace_perm));
+
+ switch (g_ace->ace_type) {
+ case GPFS_ACL_USER:
+ ace->a_type = SMB_ACL_USER;
+ ace->uid = (uid_t)g_ace->ace_who;
+ break;
+ case GPFS_ACL_USER_OBJ:
+ ace->a_type = SMB_ACL_USER_OBJ;
+ break;
+ case GPFS_ACL_GROUP:
+ ace->a_type = SMB_ACL_GROUP;
+ ace->gid = (gid_t)g_ace->ace_who;
+ break;
+ case GPFS_ACL_GROUP_OBJ:
+ ace->a_type = SMB_ACL_GROUP_OBJ;
+ break;
+ case GPFS_ACL_OTHER:
+ ace->a_type = SMB_ACL_OTHER;
+ break;
+ case GPFS_ACL_MASK:
+ ace->a_type = SMB_ACL_MASK;
+ break;
+ default:
+ DEBUG(10, ("Got invalid ace_type: %d\n",
+ g_ace->ace_type));
+ errno = EINVAL;
+ SAFE_FREE(result);
+ return NULL;
+ }
+
+ ace->a_perm = 0;
+ ace->a_perm |= (g_ace->ace_perm & ACL_PERM_READ) ?
+ SMB_ACL_READ : 0;
+ ace->a_perm |= (g_ace->ace_perm & ACL_PERM_WRITE) ?
+ SMB_ACL_WRITE : 0;
+ ace->a_perm |= (g_ace->ace_perm & ACL_PERM_EXECUTE) ?
+ SMB_ACL_EXECUTE : 0;
+
+ DEBUGADD(10, ("Converted to %d perm %x\n",
+ ace->a_type, ace->a_perm));
+ }
+
+ return result;
+}
+
+static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type)
+{
+ struct gpfs_acl *pacl;
+ SMB_ACL_T result = NULL;
+
+ pacl = gpfs_getacl_alloc(path, type);
+
+ if (pacl == NULL) {
+ DEBUG(10, ("gpfs_getacl failed for %s with %s\n",
+ path, strerror(errno)));
+ if (errno == 0) {
+ errno = EINVAL;
+ }
+ goto done;
+ }
+
+ if (pacl->acl_version != GPFS_ACL_VERSION_POSIX) {
+ DEBUG(10, ("Got acl version %d, expected %d\n",
+ pacl->acl_version, GPFS_ACL_VERSION_POSIX));
+ errno = EINVAL;
+ goto done;
+ }
+
+ DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
+ pacl->acl_len, pacl->acl_level, pacl->acl_version,
+ pacl->acl_nace));
+
+ result = gpfs2smb_acl(pacl);
+ if (result == NULL) {
+ goto done;
+ }
+
+ done:
+
+ if (errno != 0) {
+ SAFE_FREE(result);
+ }
+ return result;
+}
+
+SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
+
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ gpfs_aclType_t gpfs_type;
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ gpfs_type = GPFS_ACL_TYPE_ACCESS;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ gpfs_type = GPFS_ACL_TYPE_DEFAULT;
+ break;
+ default:
+ DEBUG(0, ("Got invalid type: %d\n", type));
+ smb_panic("exiting");
+ }
+
+ return gpfsacl_get_posix_acl(path_p, gpfs_type);
+}
+
+SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
+}
+
+static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
+ SMB_ACL_TYPE_T type)
+{
+ gpfs_aclLen_t len;
+ struct gpfs_acl *result;
+ int i;
+ union gpfs_ace_union
+ {
+ gpfs_ace_v1_t ace_v1[1]; /* when GPFS_ACL_VERSION_POSIX */
+ gpfs_ace_v4_t ace_v4[1]; /* when GPFS_ACL_VERSION_NFS4 */
+ };
+
+ DEBUG(10, ("smb2gpfs_acl: Got ACL with %d entries\n", pacl->count));
+
+ len = sizeof(struct gpfs_acl) - sizeof(union gpfs_ace_union) +
+ (pacl->count)*sizeof(gpfs_ace_v1_t);
+
+ result = SMB_MALLOC(len);
+ if (result == NULL) {
+ errno = ENOMEM;
+ return result;
+ }
+
+ result->acl_len = len;
+ result->acl_level = 0;
+ result->acl_version = GPFS_ACL_VERSION_POSIX;
+ result->acl_type = (type == SMB_ACL_TYPE_DEFAULT) ?
+ GPFS_ACL_TYPE_DEFAULT : GPFS_ACL_TYPE_ACCESS;
+ result->acl_nace = pacl->count;
+
+ for (i=0; i<pacl->count; i++) {
+ const struct smb_acl_entry *ace = &pacl->acl[i];
+ struct gpfs_ace_v1 *g_ace = &result->ace_v1[i];
+
+ DEBUG(10, ("Converting type %d perm %x\n",
+ (int)ace->a_type, (int)ace->a_perm));
+
+ g_ace->ace_perm = 0;
+
+ switch(ace->a_type) {
+ case SMB_ACL_USER:
+ g_ace->ace_type = GPFS_ACL_USER;
+ g_ace->ace_who = (gpfs_uid_t)ace->uid;
+ break;
+ case SMB_ACL_USER_OBJ:
+ g_ace->ace_type = GPFS_ACL_USER_OBJ;
+ g_ace->ace_perm |= ACL_PERM_CONTROL;
+ g_ace->ace_who = 0;
+ break;
+ case SMB_ACL_GROUP:
+ g_ace->ace_type = GPFS_ACL_GROUP;
+ g_ace->ace_who = (gpfs_uid_t)ace->gid;
+ break;
+ case SMB_ACL_GROUP_OBJ:
+ g_ace->ace_type = GPFS_ACL_GROUP_OBJ;
+ g_ace->ace_who = 0;
+ break;
+ case SMB_ACL_MASK:
+ g_ace->ace_type = GPFS_ACL_MASK;
+ g_ace->ace_perm = 0x8f;
+ g_ace->ace_who = 0;
+ break;
+ case SMB_ACL_OTHER:
+ g_ace->ace_type = GPFS_ACL_OTHER;
+ g_ace->ace_who = 0;
+ break;
+ default:
+ DEBUG(10, ("Got invalid ace_type: %d\n", ace->a_type));
+ errno = EINVAL;
+ SAFE_FREE(result);
+ return NULL;
+ }
+
+ g_ace->ace_perm |= (ace->a_perm & SMB_ACL_READ) ?
+ ACL_PERM_READ : 0;
+ g_ace->ace_perm |= (ace->a_perm & SMB_ACL_WRITE) ?
+ ACL_PERM_WRITE : 0;
+ g_ace->ace_perm |= (ace->a_perm & SMB_ACL_EXECUTE) ?
+ ACL_PERM_EXECUTE : 0;
+
+ DEBUGADD(10, ("Converted to %d id %d perm %x\n",
+ g_ace->ace_type, g_ace->ace_who, g_ace->ace_perm));
+ }
+
+ return result;
+}
+
+int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
+
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ struct gpfs_acl *gpfs_acl;
+ int result;
+
+ gpfs_acl = smb2gpfs_acl(theacl, type);
+ if (gpfs_acl == NULL) {
+ return -1;
+ }
+
+ result = smbd_gpfs_putacl((char *)name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gpfs_acl);
+
+ SAFE_FREE(gpfs_acl);
+ return result;
+}
+
+int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+
+ const char *path)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple gpfs_op_tuples[] = {
+
+ {SMB_VFS_OP(vfs_gpfs_kernel_flock),
+ SMB_VFS_OP_KERNEL_FLOCK,
+ SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(vfs_gpfs_setlease),
+ SMB_VFS_OP_LINUX_SETLEASE,
+ SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(gpfsacl_fget_nt_acl),
+ SMB_VFS_OP_FGET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_get_nt_acl),
+ SMB_VFS_OP_GET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_fset_nt_acl),
+ SMB_VFS_OP_FSET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_set_nt_acl),
+ SMB_VFS_OP_SET_NT_ACL,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(gpfsacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+
+};
+
+
+NTSTATUS vfs_gpfs_init(void);
+NTSTATUS vfs_gpfs_init(void)
+{
+ init_gpfs();
+
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",
+ gpfs_op_tuples);
+}
diff --git a/source/modules/vfs_hpuxacl.c b/source/modules/vfs_hpuxacl.c
new file mode 100644
index 00000000000..aeb078c32dc
--- /dev/null
+++ b/source/modules/vfs_hpuxacl.c
@@ -0,0 +1,105 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set hpux acls
+ Copyright (C) Michael Adam 2006
+
+ 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"
+
+/* prototypes for private functions first - for clarity */
+
+/* public functions - the api */
+
+SMB_ACL_T hpuxacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ errno = ENOTSUP;
+ return NULL;
+}
+
+SMB_ACL_T hpuxacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ errno = ENOTSUP;
+ return NULL;
+}
+
+int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int hpuxacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int hpuxacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/* private functions */
+
+/* VFS operations structure */
+
+static vfs_op_tuple hpuxacl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(hpuxacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(hpuxacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(hpuxacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(hpuxacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(hpuxacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_hpuxacl_init(void);
+NTSTATUS vfs_hpuxacl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "hpuxacl",
+ hpuxacl_op_tuples);
+}
+
+/* ENTE */
diff --git a/source/modules/vfs_irixacl.c b/source/modules/vfs_irixacl.c
new file mode 100644
index 00000000000..d80b34b24b1
--- /dev/null
+++ b/source/modules/vfs_irixacl.c
@@ -0,0 +1,105 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set irix acls
+ Copyright (C) Michael Adam 2006
+
+ 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"
+
+/* prototypes for private functions first - for clarity */
+
+/* public functions - the api */
+
+SMB_ACL_T irixacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ errno = ENOTSUP;
+ return NULL;
+}
+
+SMB_ACL_T irixacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ errno = ENOTSUP;
+ return NULL;
+}
+
+int irixacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int irixacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int irixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/* private functions */
+
+/* VFS operations structure */
+
+static vfs_op_tuple irixacl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(irixacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(irixacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(irixacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(irixacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(irixacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_irixacl_init(void);
+NTSTATUS vfs_irixacl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "irixacl",
+ irixacl_op_tuples);
+}
+
+/* ENTE */
diff --git a/source/modules/vfs_netatalk.c b/source/modules/vfs_netatalk.c
index e9d4360cd80..7176919a7dc 100644
--- a/source/modules/vfs_netatalk.c
+++ b/source/modules/vfs_netatalk.c
@@ -172,11 +172,11 @@ static void atalk_rrmdir(TALLOC_CTX *ctx, char *path)
/* Directory operations */
-SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
{
SMB_STRUCT_DIR *ret = 0;
- ret = SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr);
+ ret = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
/*
* when we try to perform delete operation upon file which has fork
@@ -187,19 +187,19 @@ SMB_STRUCT_DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connectio
* list then it would be nice to add one.
*/
- atalk_add_to_list(&conn->hide_list);
- atalk_add_to_list(&conn->veto_list);
+ atalk_add_to_list(&handle->conn->hide_list);
+ atalk_add_to_list(&handle->conn->veto_list);
return ret;
}
-static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+static int atalk_rmdir(struct vfs_handle_struct *handle, const char *path)
{
BOOL add = False;
TALLOC_CTX *ctx = 0;
char *dpath;
- if (!conn || !conn->origpath || !path) goto exit_rmdir;
+ if (!handle->conn->origpath || !path) goto exit_rmdir;
/* due to there is no way to change bDeleteVetoFiles variable
* from this module, gotta use talloc stuff..
@@ -211,19 +211,19 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struc
goto exit_rmdir;
if (!(dpath = talloc_asprintf(ctx, "%s/%s%s",
- conn->origpath, path, add ? "/"APPLEDOUBLE : "")))
+ handle->conn->origpath, path, add ? "/"APPLEDOUBLE : "")))
goto exit_rmdir;
atalk_rrmdir(ctx, dpath);
exit_rmdir:
talloc_destroy(ctx);
- return SMB_VFS_NEXT_RMDIR(handle, conn, path);
+ return SMB_VFS_NEXT_RMDIR(handle, path);
}
/* File operations */
-static int atalk_rename(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname)
+static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, const char *newname)
{
int ret = 0;
char *adbl_path = 0;
@@ -232,14 +232,14 @@ static int atalk_rename(struct vfs_handle_struct *handle, struct connection_stru
SMB_STRUCT_STAT orig_info;
TALLOC_CTX *ctx;
- ret = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname);
+ ret = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
- if (!conn || !oldname) return ret;
+ if (!oldname) return ret;
if (!(ctx = talloc_init("rename_file")))
return ret;
- if (atalk_build_paths(ctx, conn->origpath, oldname, &adbl_path, &orig_path,
+ if (atalk_build_paths(ctx, handle->conn->origpath, oldname, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
return ret;
@@ -255,7 +255,7 @@ exit_rename:
return ret;
}
-static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
+static int atalk_unlink(struct vfs_handle_struct *handle, const char *path)
{
int ret = 0, i;
char *adbl_path = 0;
@@ -264,25 +264,25 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru
SMB_STRUCT_STAT orig_info;
TALLOC_CTX *ctx;
- ret = SMB_VFS_NEXT_UNLINK(handle, conn, path);
+ ret = SMB_VFS_NEXT_UNLINK(handle, path);
- if (!conn || !path) return ret;
+ if (!path) return ret;
/* no .AppleDouble sync if veto or hide list is empty,
* otherwise "Cannot find the specified file" error will be caused
*/
- if (!conn->veto_list) return ret;
- if (!conn->hide_list) return ret;
+ if (!handle->conn->veto_list) return ret;
+ if (!handle->conn->hide_list) return ret;
- for (i = 0; conn->veto_list[i].name; i ++) {
- if (strstr(conn->veto_list[i].name, APPLEDOUBLE))
+ for (i = 0; handle->conn->veto_list[i].name; i ++) {
+ if (strstr(handle->conn->veto_list[i].name, APPLEDOUBLE))
break;
}
- if (!conn->veto_list[i].name) {
- for (i = 0; conn->hide_list[i].name; i ++) {
- if (strstr(conn->hide_list[i].name, APPLEDOUBLE))
+ if (!handle->conn->veto_list[i].name) {
+ for (i = 0; handle->conn->hide_list[i].name; i ++) {
+ if (strstr(handle->conn->hide_list[i].name, APPLEDOUBLE))
break;
else {
DEBUG(3, ("ATALK: %s is not hidden, skipped..\n",
@@ -295,7 +295,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_stru
if (!(ctx = talloc_init("unlink_file")))
return ret;
- if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path,
+ if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
return ret;
@@ -311,7 +311,7 @@ exit_unlink:
return ret;
}
-static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode)
+static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode)
{
int ret = 0;
char *adbl_path = 0;
@@ -320,14 +320,14 @@ static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struc
SMB_STRUCT_STAT orig_info;
TALLOC_CTX *ctx;
- ret = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
+ ret = SMB_VFS_NEXT_CHMOD(handle, path, mode);
- if (!conn || !path) return ret;
+ if (!path) return ret;
if (!(ctx = talloc_init("chmod_file")))
return ret;
- if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path,
+ if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
return ret;
@@ -343,7 +343,7 @@ exit_chmod:
return ret;
}
-static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid)
+static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
{
int ret = 0;
char *adbl_path = 0;
@@ -352,14 +352,14 @@ static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struc
SMB_STRUCT_STAT orig_info;
TALLOC_CTX *ctx;
- ret = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid);
+ ret = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
- if (!conn || !path) return ret;
+ if (!path) return ret;
if (!(ctx = talloc_init("chown_file")))
return ret;
- if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path,
+ if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
return ret;
@@ -394,6 +394,7 @@ static vfs_op_tuple atalk_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_netatalk_init(void);
NTSTATUS vfs_netatalk_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "netatalk", atalk_ops);
diff --git a/source/modules/vfs_notify_fam.c b/source/modules/vfs_notify_fam.c
new file mode 100644
index 00000000000..b76046b3789
--- /dev/null
+++ b/source/modules/vfs_notify_fam.c
@@ -0,0 +1,302 @@
+/*
+ * FAM file notification support.
+ *
+ * Copyright (c) James Peach 2005
+ * Copyright (c) Volker Lendecke 2007
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "includes.h"
+
+#include <fam.h>
+
+#if !defined(HAVE_FAM_H_FAMCODES_TYPEDEF)
+/* Gamin provides this typedef which means we can't use 'enum FAMCodes' as per
+ * every other FAM implementation. Phooey.
+ */
+typedef enum FAMCodes FAMCodes;
+#endif
+
+/* NOTE: There are multiple versions of FAM floating around the net, each with
+ * slight differences from the original SGI FAM implementation. In this file,
+ * we rely only on the SGI features and do not assume any extensions. For
+ * example, we do not look at FAMErrno, because it is not set by the original
+ * implementation.
+ *
+ * Random FAM links:
+ * http://oss.sgi.com/projects/fam/
+ * http://savannah.nongnu.org/projects/fam/
+ * http://sourceforge.net/projects/bsdfam/
+ */
+
+/* ------------------------------------------------------------------------- */
+
+struct fam_watch_context {
+ struct fam_watch_context *prev, *next;
+ FAMConnection *fam_connection;
+ struct FAMRequest fr;
+ struct sys_notify_context *sys_ctx;
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev);
+ void *private_data;
+ uint32_t mask; /* the inotify mask */
+ uint32_t filter; /* the windows completion filter */
+ const char *path;
+};
+
+
+/*
+ * We want one FAM connection per smbd, not one per tcon.
+ */
+static FAMConnection fam_connection;
+static BOOL fam_connection_initialized = False;
+
+static struct fam_watch_context *fam_notify_list;
+static void fam_handler(struct event_context *event_ctx,
+ struct fd_event *fd_event,
+ uint16 flags,
+ void *private_data);
+
+static NTSTATUS fam_open_connection(FAMConnection *fam_conn,
+ struct event_context *event_ctx)
+{
+ int res;
+ char *name;
+
+ ZERO_STRUCTP(fam_conn);
+ FAMCONNECTION_GETFD(fam_conn) = -1;
+
+ if (asprintf(&name, "smbd (%lu)", (unsigned long)sys_getpid()) == -1) {
+ DEBUG(0, ("No memory\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ res = FAMOpen2(fam_conn, name);
+ SAFE_FREE(name);
+
+ if (res < 0) {
+ DEBUG(10, ("FAM file change notifications not available\n"));
+ /*
+ * No idea how to get NT_STATUS from a FAM result
+ */
+ FAMCONNECTION_GETFD(fam_conn) = -1;
+ return NT_STATUS_UNEXPECTED_IO_ERROR;
+ }
+
+ if (event_add_fd(event_ctx, event_ctx,
+ FAMCONNECTION_GETFD(fam_conn),
+ EVENT_FD_READ, fam_handler,
+ (void *)fam_conn) == NULL) {
+ DEBUG(0, ("event_add_fd failed\n"));
+ FAMClose(fam_conn);
+ FAMCONNECTION_GETFD(fam_conn) = -1;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static void fam_reopen(FAMConnection *fam_conn,
+ struct event_context *event_ctx,
+ struct fam_watch_context *notify_list)
+{
+ struct fam_watch_context *ctx;
+
+ DEBUG(5, ("Re-opening FAM connection\n"));
+
+ FAMClose(fam_conn);
+
+ if (!NT_STATUS_IS_OK(fam_open_connection(fam_conn, event_ctx))) {
+ DEBUG(5, ("Re-opening fam connection failed\n"));
+ return;
+ }
+
+ for (ctx = notify_list; ctx; ctx = ctx->next) {
+ FAMMonitorDirectory(fam_conn, ctx->path, &ctx->fr, NULL);
+ }
+}
+
+static void fam_handler(struct event_context *event_ctx,
+ struct fd_event *fd_event,
+ uint16 flags,
+ void *private_data)
+{
+ FAMConnection *fam_conn = (FAMConnection *)private_data;
+ FAMEvent fam_event;
+ struct fam_watch_context *ctx;
+ struct notify_event ne;
+
+ if (FAMPending(fam_conn) == 0) {
+ DEBUG(10, ("fam_handler called but nothing pending\n"));
+ return;
+ }
+
+ if (FAMNextEvent(fam_conn, &fam_event) != 1) {
+ DEBUG(5, ("FAMNextEvent returned an error\n"));
+ TALLOC_FREE(fd_event);
+ fam_reopen(fam_conn, event_ctx, fam_notify_list);
+ return;
+ }
+
+ DEBUG(10, ("Got FAMCode %d for %s\n", fam_event.code,
+ fam_event.filename));
+
+ switch (fam_event.code) {
+ case FAMCreated:
+ ne.action = NOTIFY_ACTION_ADDED;
+ break;
+ case FAMDeleted:
+ ne.action = NOTIFY_ACTION_REMOVED;
+ break;
+ default:
+ DEBUG(10, ("Ignoring code FAMCode %d for file %s\n",
+ (int)fam_event.code, fam_event.filename));
+ return;
+ }
+
+ for (ctx = fam_notify_list; ctx; ctx = ctx->next) {
+ if (memcmp(&fam_event.fr, &ctx->fr, sizeof(FAMRequest)) == 0) {
+ break;
+ }
+ }
+
+ if (ctx == NULL) {
+ DEBUG(5, ("Discarding event for file %s\n",
+ fam_event.filename));
+ return;
+ }
+
+ if ((ne.path = strrchr_m(fam_event.filename, '\\')) == NULL) {
+ ne.path = fam_event.filename;
+ }
+
+ ctx->callback(ctx->sys_ctx, ctx->private_data, &ne);
+}
+
+static int fam_watch_context_destructor(struct fam_watch_context *ctx)
+{
+ if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) {
+ FAMCancelMonitor(&fam_connection, &ctx->fr);
+ }
+ DLIST_REMOVE(fam_notify_list, ctx);
+ return 0;
+}
+
+/*
+ add a watch. The watch is removed when the caller calls
+ talloc_free() on *handle
+*/
+static NTSTATUS fam_watch(vfs_handle_struct *vfs_handle,
+ struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data,
+ void *handle_p)
+{
+ const uint32 fam_mask = (FILE_NOTIFY_CHANGE_FILE_NAME|
+ FILE_NOTIFY_CHANGE_DIR_NAME);
+ struct fam_watch_context *watch;
+ void **handle = (void **)handle_p;
+
+ if ((e->filter & fam_mask) == 0) {
+ DEBUG(10, ("filter = %u, ignoring in FAM\n", e->filter));
+ return NT_STATUS_OK;
+ }
+
+ if (!fam_connection_initialized) {
+ if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection,
+ ctx->ev))) {
+ /*
+ * Just let smbd do all the work itself
+ */
+ return NT_STATUS_OK;
+ }
+ fam_connection_initialized = True;
+ }
+
+ if (!(watch = TALLOC_P(ctx, struct fam_watch_context))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ watch->fam_connection = &fam_connection;
+
+ watch->callback = callback;
+ watch->private_data = private_data;
+ watch->sys_ctx = ctx;
+
+ if (!(watch->path = talloc_strdup(watch, e->path))) {
+ DEBUG(0, ("talloc_asprintf failed\n"));
+ TALLOC_FREE(watch);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /*
+ * The FAM module in this early state will only take care of
+ * FAMCreated and FAMDeleted events, Leave the rest to
+ * notify_internal.c
+ */
+
+ watch->filter = fam_mask;
+ e->filter &= ~fam_mask;
+
+ DLIST_ADD(fam_notify_list, watch);
+ talloc_set_destructor(watch, fam_watch_context_destructor);
+
+ /*
+ * Only directories monitored so far
+ */
+
+ if (FAMCONNECTION_GETFD(watch->fam_connection) != -1) {
+ FAMMonitorDirectory(watch->fam_connection, watch->path,
+ &watch->fr, NULL);
+ }
+ else {
+ /*
+ * If the re-open is successful, this will establish the
+ * FAMMonitor from the list
+ */
+ fam_reopen(watch->fam_connection, ctx->ev, fam_notify_list);
+ }
+
+ *handle = (void *)watch;
+
+ return NT_STATUS_OK;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple notify_fam_op_tuples[] = {
+
+ {SMB_VFS_OP(fam_watch),
+ SMB_VFS_OP_NOTIFY_WATCH,
+ SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+
+};
+
+
+NTSTATUS vfs_notify_fam_init(void);
+NTSTATUS vfs_notify_fam_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "notify_fam",
+ notify_fam_op_tuples);
+}
diff --git a/source/modules/vfs_posixacl.c b/source/modules/vfs_posixacl.c
new file mode 100644
index 00000000000..191c4a7cb0e
--- /dev/null
+++ b/source/modules/vfs_posixacl.c
@@ -0,0 +1,392 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set posix acls
+ Copyright (C) Volker Lendecke 2006
+
+ 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"
+
+
+/* prototypes for static functions first - for clarity */
+
+static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
+ struct smb_acl_entry *ace);
+static struct smb_acl_t *smb_acl_to_internal(acl_t acl);
+static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
+static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
+
+
+/* public functions - the api */
+
+SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ struct smb_acl_t *result;
+ acl_type_t acl_type;
+ acl_t acl;
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ acl_type = ACL_TYPE_ACCESS;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ acl_type = ACL_TYPE_DEFAULT;
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+
+ acl = acl_get_file(path_p, acl_type);
+
+ if (acl == NULL) {
+ return NULL;
+ }
+
+ result = smb_acl_to_internal(acl);
+ acl_free(acl);
+ return result;
+}
+
+SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ struct smb_acl_t *result;
+ acl_t acl = acl_get_fd(fd);
+
+ if (acl == NULL) {
+ return NULL;
+ }
+
+ result = smb_acl_to_internal(acl);
+ acl_free(acl);
+ return result;
+}
+
+int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ int res;
+ acl_type_t acl_type;
+ acl_t acl;
+
+ DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type));
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ acl_type = ACL_TYPE_ACCESS;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ acl_type = ACL_TYPE_DEFAULT;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((acl = smb_acl_to_posix(theacl)) == NULL) {
+ return -1;
+ }
+ res = acl_set_file(name, acl_type, acl);
+ if (res != 0) {
+ DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
+ }
+ acl_free(acl);
+ return res;
+}
+
+int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ int res;
+ acl_t acl = smb_acl_to_posix(theacl);
+ if (acl == NULL) {
+ return -1;
+ }
+ res = acl_set_fd(fd, acl);
+ acl_free(acl);
+ return res;
+}
+
+int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ return acl_delete_def_file(path);
+}
+
+
+/* private functions */
+
+static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
+ struct smb_acl_entry *ace)
+{
+ acl_tag_t tag;
+ acl_permset_t permset;
+
+ if (acl_get_tag_type(posix_ace, &tag) != 0) {
+ DEBUG(0, ("smb_acl_get_tag_type failed\n"));
+ return False;
+ }
+
+ switch(tag) {
+ case ACL_USER:
+ ace->a_type = SMB_ACL_USER;
+ break;
+ case ACL_USER_OBJ:
+ ace->a_type = SMB_ACL_USER_OBJ;
+ break;
+ case ACL_GROUP:
+ ace->a_type = SMB_ACL_GROUP;
+ break;
+ case ACL_GROUP_OBJ:
+ ace->a_type = SMB_ACL_GROUP_OBJ;
+ break;
+ case ACL_OTHER:
+ ace->a_type = SMB_ACL_OTHER;
+ break;
+ case ACL_MASK:
+ ace->a_type = SMB_ACL_MASK;
+ break;
+ default:
+ DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
+ return False;
+ }
+ switch(ace->a_type) {
+ case SMB_ACL_USER: {
+ uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace);
+ if (puid == NULL) {
+ DEBUG(0, ("smb_acl_get_qualifier failed\n"));
+ return False;
+ }
+ ace->uid = *puid;
+ acl_free(puid);
+ break;
+ }
+
+ case SMB_ACL_GROUP: {
+ gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
+ if (pgid == NULL) {
+ DEBUG(0, ("smb_acl_get_qualifier failed\n"));
+ return False;
+ }
+ ace->gid = *pgid;
+ acl_free(pgid);
+ break;
+ }
+ default:
+ break;
+ }
+ if (acl_get_permset(posix_ace, &permset) != 0) {
+ DEBUG(0, ("smb_acl_get_mode failed\n"));
+ return False;
+ }
+ ace->a_perm = 0;
+ ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0);
+ ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
+ ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
+ return True;
+}
+
+static struct smb_acl_t *smb_acl_to_internal(acl_t acl)
+{
+ struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
+ int entry_id = ACL_FIRST_ENTRY;
+ acl_entry_t e;
+ if (result == NULL) {
+ return NULL;
+ }
+ ZERO_STRUCTP(result);
+ while (acl_get_entry(acl, entry_id, &e) == 1) {
+
+ entry_id = ACL_NEXT_ENTRY;
+
+ result = (struct smb_acl_t *)SMB_REALLOC(
+ result, sizeof(struct smb_acl_t) +
+ (sizeof(struct smb_acl_entry) * (result->count+1)));
+ if (result == NULL) {
+ DEBUG(0, ("SMB_REALLOC failed\n"));
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ if (!smb_ace_to_internal(e, &result->acl[result->count])) {
+ SAFE_FREE(result);
+ return NULL;
+ }
+
+ result->count += 1;
+ }
+ return result;
+}
+
+static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
+{
+ int ret;
+ acl_permset_t permset;
+
+ if ((ret = acl_get_permset(entry, &permset)) != 0) {
+ return ret;
+ }
+ if ((ret = acl_clear_perms(permset)) != 0) {
+ return ret;
+ }
+ if ((perm & SMB_ACL_READ) &&
+ ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
+ return ret;
+ }
+ if ((perm & SMB_ACL_WRITE) &&
+ ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
+ return ret;
+ }
+ if ((perm & SMB_ACL_EXECUTE) &&
+ ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
+ return ret;
+ }
+ return acl_set_permset(entry, permset);
+}
+
+static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
+{
+ acl_t result;
+ int i;
+
+ result = acl_init(acl->count);
+ if (result == NULL) {
+ DEBUG(10, ("acl_init failed\n"));
+ return NULL;
+ }
+
+ for (i=0; i<acl->count; i++) {
+ const struct smb_acl_entry *entry = &acl->acl[i];
+ acl_entry_t e;
+ acl_tag_t tag;
+
+ if (acl_create_entry(&result, &e) != 0) {
+ DEBUG(1, ("acl_create_entry failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+
+ switch (entry->a_type) {
+ case SMB_ACL_USER:
+ tag = ACL_USER;
+ break;
+ case SMB_ACL_USER_OBJ:
+ tag = ACL_USER_OBJ;
+ break;
+ case SMB_ACL_GROUP:
+ tag = ACL_GROUP;
+ break;
+ case SMB_ACL_GROUP_OBJ:
+ tag = ACL_GROUP_OBJ;
+ break;
+ case SMB_ACL_OTHER:
+ tag = ACL_OTHER;
+ break;
+ case SMB_ACL_MASK:
+ tag = ACL_MASK;
+ break;
+ default:
+ DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
+ goto fail;
+ }
+
+ if (acl_set_tag_type(e, tag) != 0) {
+ DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
+ tag, strerror(errno)));
+ goto fail;
+ }
+
+ switch (entry->a_type) {
+ case SMB_ACL_USER:
+ if (acl_set_qualifier(e, &entry->uid) != 0) {
+ DEBUG(1, ("acl_set_qualifiier failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+ break;
+ case SMB_ACL_GROUP:
+ if (acl_set_qualifier(e, &entry->gid) != 0) {
+ DEBUG(1, ("acl_set_qualifiier failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+ break;
+ default: /* Shut up, compiler! :-) */
+ break;
+ }
+
+ if (smb_acl_set_mode(e, entry->a_perm) != 0) {
+ goto fail;
+ }
+ }
+
+ if (acl_valid(result) != 0) {
+ DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
+ strerror(errno)));
+ goto fail;
+ }
+
+ return result;
+
+ fail:
+ if (result != NULL) {
+ acl_free(result);
+ }
+ return NULL;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple posixacl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(posixacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(posixacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(posixacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(posixacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(posixacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_posixacl_init(void);
+NTSTATUS vfs_posixacl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
+ posixacl_op_tuples);
+}
diff --git a/source/modules/vfs_prealloc.c b/source/modules/vfs_prealloc.c
new file mode 100644
index 00000000000..2e0b8b18b49
--- /dev/null
+++ b/source/modules/vfs_prealloc.c
@@ -0,0 +1,215 @@
+/*
+ * XFS preallocation support module.
+ *
+ * Copyright (c) James Peach 2006
+ *
+ * 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"
+
+/* Extent preallocation module.
+ *
+ * The purpose of this module is to preallocate space on the filesystem when
+ * we have a good idea of how large files are supposed to be. This lets writes
+ * proceed without having to allocate new extents and results in better file
+ * layouts on disk.
+ *
+ * Currently only implemented for XFS. This module is based on an original idea
+ * and implementation by Sebastian Brings.
+ *
+ * Tunables.
+ *
+ * prealloc: <ext> Number of bytes to preallocate for a file with
+ * the matching extension.
+ * prealloc:debug Debug level at which to emit messages.
+ *
+ * Example.
+ *
+ * prealloc:mpeg = 500M # Preallocate *.mpeg to 500 MiB.
+ */
+
+#ifdef HAVE_XFS_LIBXFS_H
+#include <xfs/libxfs.h>
+#define lock_type xfs_flock64_t
+#else
+#define lock_type struct flock64
+#endif
+
+#define MODULE "prealloc"
+static int module_debug;
+
+static int preallocate_space(int fd, SMB_OFF_T size)
+{
+ lock_type fl = {0};
+ int err;
+
+ if (size <= 0) {
+ return 0;
+ }
+
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = size;
+
+ /* IMPORTANT: We use RESVSP because we want the extents to be
+ * allocated, but we don't want the allocation to show up in
+ * st_size or persist after the close(2).
+ */
+
+#if defined(XFS_IOC_RESVSP64)
+ /* On Linux this comes in via libxfs.h. */
+ err = xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
+#elif defined(F_RESVSP64)
+ /* On IRIX, this comes from fcntl.h. */
+ err = fcntl(fd, F_RESVSP64, &fl);
+#else
+ err = -1;
+ errno = ENOSYS;
+#endif
+
+ if (err) {
+ DEBUG(module_debug,
+ ("%s: preallocate failed on fd=%d size=%lld: %s\n",
+ MODULE, fd, (long long)size, strerror(errno)));
+ }
+
+ return err;
+}
+
+static int prealloc_connect(
+ struct vfs_handle_struct * handle,
+ const char * service,
+ const char * user)
+{
+ module_debug = lp_parm_int(SNUM(handle->conn),
+ MODULE, "debug", 100);
+
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
+
+static int prealloc_open(vfs_handle_struct* handle,
+ const char * fname,
+ files_struct * fsp,
+ int flags,
+ mode_t mode)
+{
+ int fd;
+ off64_t size = 0;
+
+ const char * dot;
+ char fext[10];
+
+ if (!(flags & (O_CREAT|O_TRUNC))) {
+ /* Caller is not intending to rewrite the file. Let's not mess
+ * with the allocation in this case.
+ */
+ goto normal_open;
+ }
+
+ *fext = '\0';
+ dot = strrchr(fname, '.');
+ if (dot && *++dot) {
+ if (strlen(dot) < sizeof(fext)) {
+ strncpy(fext, dot, sizeof(fext));
+ strnorm(fext, CASE_LOWER);
+ }
+ }
+
+ if (*fext == '\0') {
+ goto normal_open;
+ }
+
+ /* Syntax for specifying preallocation size is:
+ * MODULE: <extension> = <size>
+ * where
+ * <extension> is the file extension in lower case
+ * <size> is a size like 10, 10K, 10M
+ */
+ size = conv_str_size(lp_parm_const_string(SNUM(handle->conn), MODULE,
+ fext, NULL));
+ if (size <= 0) {
+ /* No need to preallocate this file. */
+ goto normal_open;
+ }
+
+ fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+ if (fd < 0) {
+ return fd;
+ }
+
+ /* Prellocate only if the file is being created or replaced. Note that
+ * Samba won't ever pass down O_TRUNC, which is why we have to handle
+ * truncate calls specially.
+ */
+ if ((flags & O_CREAT) || (flags & O_TRUNC)) {
+ SMB_OFF_T * psize;
+
+ psize = VFS_ADD_FSP_EXTENSION(handle, fsp, SMB_OFF_T);
+ if (psize == NULL || *psize == -1) {
+ return fd;
+ }
+
+ DEBUG(module_debug,
+ ("%s: preallocating %s (fd=%d) to %lld bytes\n",
+ MODULE, fname, fd, (long long)size));
+
+ *psize = size;
+ if (preallocate_space(fd, *psize) < 0) {
+ VFS_REMOVE_FSP_EXTENSION(handle, fsp);
+ }
+ }
+
+ return fd;
+
+normal_open:
+ /* We are not creating or replacing a file. Skip the
+ * preallocation.
+ */
+ DEBUG(module_debug, ("%s: skipping preallocation for %s\n",
+ MODULE, fname));
+ return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+}
+
+static int prealloc_ftruncate(vfs_handle_struct * handle,
+ files_struct * fsp,
+ int fd,
+ SMB_OFF_T offset)
+{
+ SMB_OFF_T *psize;
+ int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset);
+
+ /* Maintain the allocated space even in the face of truncates. */
+ if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) {
+ preallocate_space(fd, *psize);
+ }
+
+ return ret;
+}
+
+static vfs_op_tuple prealloc_op_tuples[] = {
+ {SMB_VFS_OP(prealloc_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(prealloc_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(prealloc_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
+ {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_prealloc_init(void);
+NTSTATUS vfs_prealloc_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+ MODULE, prealloc_op_tuples);
+}
+
diff --git a/source/modules/vfs_readonly.c b/source/modules/vfs_readonly.c
index ee9e40c2fca..721e59430c2 100644
--- a/source/modules/vfs_readonly.c
+++ b/source/modules/vfs_readonly.c
@@ -55,7 +55,6 @@
#define MODULE_NAME "readonly"
static int readonly_connect(vfs_handle_struct *handle,
- connection_struct *conn,
const char *service,
const char *user)
{
@@ -71,10 +70,10 @@ static int readonly_connect(vfs_handle_struct *handle,
time_t end_period = get_date(period[1], &current_time);
if ((current_time >= begin_period) && (current_time <= end_period)) {
- conn->read_only = True;
+ handle->conn->read_only = True;
}
- return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
} else {
@@ -92,6 +91,7 @@ static vfs_op_tuple readonly_op_tuples[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_readonly_init(void);
NTSTATUS vfs_readonly_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE_NAME, readonly_op_tuples);
diff --git a/source/modules/vfs_recycle.c b/source/modules/vfs_recycle.c
index 42f2f51416e..121454315fb 100644
--- a/source/modules/vfs_recycle.c
+++ b/source/modules/vfs_recycle.c
@@ -32,9 +32,9 @@ static int vfs_recycle_debug_level = DBGC_VFS;
#undef DBGC_CLASS
#define DBGC_CLASS vfs_recycle_debug_level
-static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
-static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn);
-static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *name);
+static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user);
+static void recycle_disconnect(vfs_handle_struct *handle);
+static int recycle_unlink(vfs_handle_struct *handle, const char *name);
static vfs_op_tuple recycle_ops[] = {
@@ -48,20 +48,20 @@ static vfs_op_tuple recycle_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
-static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
+static int recycle_connect(vfs_handle_struct *handle, const char *service, const char *user)
{
DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n",
service,user));
- return SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
+ return SMB_VFS_NEXT_CONNECT(handle, service, user);
}
-static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+static void recycle_disconnect(vfs_handle_struct *handle)
{
DEBUG(10,("recycle_disconnect() connect to service[%s].\n",
- lp_servicename(SNUM(conn))));
+ lp_servicename(SNUM(handle->conn))));
- SMB_VFS_NEXT_DISCONNECT(handle, conn);
+ SMB_VFS_NEXT_DISCONNECT(handle);
}
static const char *recycle_repository(vfs_handle_struct *handle)
@@ -202,7 +202,7 @@ static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname
{
SMB_STRUCT_STAT st;
- if (SMB_VFS_NEXT_STAT(handle, handle->conn, dname, &st) == 0) {
+ if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
return True;
}
@@ -215,7 +215,7 @@ static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname)
{
SMB_STRUCT_STAT st;
- if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) == 0) {
+ if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) {
if (S_ISREG(st.st_mode)) {
return True;
}
@@ -234,7 +234,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn
{
SMB_STRUCT_STAT st;
- if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+ if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
return (SMB_OFF_T)0;
}
@@ -280,7 +280,7 @@ static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
DEBUG(10, ("recycle: dir %s already exists\n", new_dir));
else {
DEBUG(5, ("recycle: creating new dir %s\n", new_dir));
- if (SMB_VFS_NEXT_MKDIR(handle, handle->conn, new_dir, mode) != 0) {
+ if (SMB_VFS_NEXT_MKDIR(handle, new_dir, mode) != 0) {
DEBUG(1,("recycle: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
ret = False;
goto done;
@@ -354,7 +354,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL
struct utimbuf tb;
time_t currtime;
- if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+ if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
return;
}
@@ -362,16 +362,19 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL
tb.actime = currtime;
tb.modtime = touch_mtime ? currtime : st.st_mtime;
- if (SMB_VFS_NEXT_UTIME(handle, handle->conn, fname, &tb) == -1 ) {
+ if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) {
DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
}
}
+extern userdom_struct current_user_info;
+
/**
* Check if file should be recycled
**/
-static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name)
+static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
{
+ connection_struct *conn = handle->conn;
char *path_name = NULL;
char *temp_name = NULL;
char *final_name = NULL;
@@ -383,7 +386,12 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
BOOL exist;
int rc = -1;
- repository = alloc_sub_conn(conn, recycle_repository(handle));
+ repository = talloc_sub_advanced(NULL, lp_servicename(SNUM(conn)),
+ conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ recycle_repository(handle));
ALLOC_CHECK(repository, done);
/* shouldn't we allow absolute path names here? --metze */
/* Yes :-). JRA. */
@@ -391,14 +399,14 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
if(!repository || *(repository) == '\0') {
DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
/* we don't recycle the recycle bin... */
if (strncmp(file_name, repository, strlen(repository)) == 0) {
DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n"));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
@@ -408,7 +416,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
*
if(fsize == 0) {
DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name));
- rc = SMB_VFS_NEXT_UNLINK(handle,conn,file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle,file_name);
goto done;
}
*/
@@ -420,18 +428,18 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
maxsize = recycle_maxsize(handle);
if(maxsize > 0 && file_size > maxsize) {
DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
/* FIXME: this is wrong: moving files with rename does not change the disk space
* allocation
*
- space_avail = SMB_VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
+ space_avail = SMB_VFS_NEXT_DISK_FREE(handle, ".", True, &bsize, &dfree, &dsize) * 1024L;
DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size));
if(space_avail < file_size) {
DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
*/
@@ -456,7 +464,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
if (matchparam(recycle_exclude(handle), base)) {
DEBUG(3, ("recycle: file %s is excluded \n", base));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
@@ -466,7 +474,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
*/
if (checkparam(recycle_exclude_dir(handle), path_name)) {
DEBUG(3, ("recycle: directory %s is excluded \n", path_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
@@ -484,7 +492,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
DEBUG(10, ("recycle: Creating directory %s\n", temp_name));
if (recycle_create_dir(handle, temp_name) == False) {
DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
}
@@ -497,7 +505,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
if (recycle_file_exist(handle, final_name)) {
if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) {
DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name));
- if (SMB_VFS_NEXT_UNLINK(handle, conn, final_name) != 0) {
+ if (SMB_VFS_NEXT_UNLINK(handle, final_name) != 0) {
DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno)));
}
}
@@ -511,10 +519,10 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co
}
DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name));
- rc = SMB_VFS_NEXT_RENAME(handle, conn, file_name, final_name);
+ rc = SMB_VFS_NEXT_RENAME(handle, file_name, final_name);
if (rc != 0) {
DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
- rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
@@ -526,10 +534,11 @@ done:
SAFE_FREE(path_name);
SAFE_FREE(temp_name);
SAFE_FREE(final_name);
- SAFE_FREE(repository);
+ TALLOC_FREE(repository);
return rc;
}
+NTSTATUS vfs_recycle_init(void);
NTSTATUS vfs_recycle_init(void)
{
NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "recycle", recycle_ops);
diff --git a/source/modules/vfs_shadow_copy.c b/source/modules/vfs_shadow_copy.c
index db1c8d007dc..f9a76ec72d2 100644
--- a/source/modules/vfs_shadow_copy.c
+++ b/source/modules/vfs_shadow_copy.c
@@ -72,10 +72,10 @@ static BOOL shadow_copy_match_name(const char *name)
return False;
}
-static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
+static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
{
shadow_copy_Dir *dirp;
- SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,conn,fname,mask,attr);
+ SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr);
if (!p) {
DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname));
@@ -85,7 +85,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
dirp = SMB_MALLOC_P(shadow_copy_Dir);
if (!dirp) {
DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
- SMB_VFS_NEXT_CLOSEDIR(handle,conn,p);
+ SMB_VFS_NEXT_CLOSEDIR(handle,p);
return NULL;
}
@@ -94,7 +94,7 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
while (True) {
SMB_STRUCT_DIRENT *d;
- d = SMB_VFS_NEXT_READDIR(handle, conn, p);
+ d = SMB_VFS_NEXT_READDIR(handle, p);
if (d == NULL) {
break;
}
@@ -115,11 +115,11 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
dirp->dirs[dirp->num++] = *d;
}
- SMB_VFS_NEXT_CLOSEDIR(handle,conn,p);
+ SMB_VFS_NEXT_CLOSEDIR(handle,p);
return((SMB_STRUCT_DIR *)dirp);
}
-SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
{
shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
@@ -130,7 +130,7 @@ SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, connection_str
return NULL;
}
-static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp, long offset)
+static void shadow_copy_seekdir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp, long offset)
{
shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
@@ -139,19 +139,19 @@ static void shadow_copy_seekdir(struct vfs_handle_struct *handle, struct connect
}
}
-static long shadow_copy_telldir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static long shadow_copy_telldir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
{
shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
return( dirp->pos ) ;
}
-static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
{
shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
dirp->pos = 0 ;
}
-int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *_dirp)
+static int shadow_copy_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
{
shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
@@ -163,7 +163,7 @@ int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB
static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
{
- SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn,fsp->conn->connectpath,NULL,0);
+ SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0);
shadow_copy_data->num_volumes = 0;
shadow_copy_data->labels = NULL;
@@ -177,7 +177,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
SHADOW_COPY_LABEL *tlabels;
SMB_STRUCT_DIRENT *d;
- d = SMB_VFS_NEXT_READDIR(handle, fsp->conn, p);
+ d = SMB_VFS_NEXT_READDIR(handle, p);
if (d == NULL) {
break;
}
@@ -200,7 +200,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
(shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
if (tlabels == NULL) {
DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
- SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p);
+ SMB_VFS_NEXT_CLOSEDIR(handle,p);
return -1;
}
@@ -209,7 +209,7 @@ static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_str
shadow_copy_data->labels = tlabels;
}
- SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p);
+ SMB_VFS_NEXT_CLOSEDIR(handle,p);
return 0;
}
@@ -228,6 +228,7 @@ static vfs_op_tuple shadow_copy_ops[] = {
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
+NTSTATUS vfs_shadow_copy_init(void);
NTSTATUS vfs_shadow_copy_init(void)
{
NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy", shadow_copy_ops);
diff --git a/source/modules/vfs_solarisacl.c b/source/modules/vfs_solarisacl.c
new file mode 100644
index 00000000000..3ec01b2a391
--- /dev/null
+++ b/source/modules/vfs_solarisacl.c
@@ -0,0 +1,789 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set Solaris ACLs
+ Copyright (C) Michael Adam 2006
+
+ 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"
+
+
+/* typedef struct acl SOLARIS_ACE_T; */
+typedef aclent_t SOLARIS_ACE_T;
+typedef aclent_t *SOLARIS_ACL_T;
+typedef int SOLARIS_ACL_TAG_T; /* the type of an ACL entry */
+typedef o_mode_t SOLARIS_PERM_T;
+
+/* for convenience: check if solaris acl entry is a default entry? */
+#define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT)
+#define _IS_OF_TYPE(ace, type) ( \
+ (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \
+ || \
+ (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \
+)
+
+
+/* prototypes for private functions */
+
+static SOLARIS_ACL_T solaris_acl_init(int count);
+static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl,
+ SOLARIS_ACL_T *solariacl, int *count,
+ SMB_ACL_TYPE_T type);
+static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count,
+ SMB_ACL_TYPE_T type);
+static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag);
+static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag);
+static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
+ SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type);
+static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl,
+ int *count);
+static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
+static BOOL solaris_acl_sort(SOLARIS_ACL_T acl, int count);
+static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
+static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
+static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
+
+
+/* public functions - the api */
+
+SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ SMB_ACL_T result = NULL;
+ int count;
+ SOLARIS_ACL_T solaris_acl;
+
+ DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n",
+ path_p));
+
+ if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
+ DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
+ errno = EINVAL;
+ goto done;
+ }
+
+ DEBUGADD(10, ("getting %s acl\n",
+ ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
+
+ if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) {
+ goto done;
+ }
+ result = solaris_acl_to_smb_acl(solaris_acl, count, type);
+ if (result == NULL) {
+ DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
+ strerror(errno)));
+ }
+
+ done:
+ DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n",
+ ((result == NULL) ? "failed" : "succeeded" )));
+ SAFE_FREE(solaris_acl);
+ return result;
+}
+
+
+/*
+ * get the access ACL of a file referred to by a fd
+ */
+SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ SMB_ACL_T result = NULL;
+ int count;
+ SOLARIS_ACL_T solaris_acl;
+
+ DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n"));
+
+ if (!solaris_acl_get_fd(fd, &solaris_acl, &count)) {
+ goto done;
+ }
+ /*
+ * The facl call returns both ACCESS and DEFAULT acls (as present).
+ * The posix acl_get_fd function returns only the
+ * access acl. So we need to filter this out here.
+ */
+ result = solaris_acl_to_smb_acl(solaris_acl, count,
+ SMB_ACL_TYPE_ACCESS);
+ if (result == NULL) {
+ DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
+ strerror(errno)));
+ }
+
+ done:
+ DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n",
+ ((result == NULL) ? "failed" : "succeeded")));
+ SAFE_FREE(solaris_acl);
+ return NULL;
+}
+
+int solarisacl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ int ret = -1;
+ struct stat s;
+ SOLARIS_ACL_T solaris_acl;
+ int count;
+
+ DEBUG(10, ("solarisacl_sys_acl_set_file called for file '%s'\n",
+ name));
+
+ if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) {
+ errno = EINVAL;
+ DEBUG(10, ("invalid smb acl type given (%d).\n", type));
+ goto done;
+ }
+ DEBUGADD(10, ("setting %s acl\n",
+ ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
+
+ if(!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, type)) {
+ DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
+ strerror(errno)));
+ goto done;
+ }
+
+ /*
+ * if the file is a directory, there is extra work to do:
+ * since the solaris acl call stores both the access acl and
+ * the default acl as provided, we have to get the acl part
+ * that has not been specified in "type" from the file first
+ * and concatenate it with the acl provided.
+ */
+ if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
+ DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
+ goto done;
+ }
+ if (S_ISDIR(s.st_mode)) {
+ SOLARIS_ACL_T other_acl;
+ int other_count;
+ SMB_ACL_TYPE_T other_type;
+
+ other_type = (type == SMB_ACL_TYPE_ACCESS)
+ ? SMB_ACL_TYPE_DEFAULT
+ : SMB_ACL_TYPE_ACCESS;
+ DEBUGADD(10, ("getting acl from filesystem\n"));
+ if (!solaris_acl_get_file(name, &other_acl, &other_count)) {
+ DEBUG(10, ("error getting acl from directory\n"));
+ goto done;
+ }
+ DEBUG(10, ("adding %s part of fs acl to given acl\n",
+ ((other_type == SMB_ACL_TYPE_ACCESS)
+ ? "access"
+ : "default")));
+ if (!solaris_add_to_acl(&solaris_acl, &count, other_acl,
+ other_count, other_type))
+ {
+ DEBUG(10, ("error adding other acl.\n"));
+ SAFE_FREE(other_acl);
+ goto done;
+ }
+ SAFE_FREE(other_acl);
+ }
+ else if (type != SMB_ACL_TYPE_ACCESS) {
+ errno = EINVAL;
+ goto done;
+ }
+
+ if (!solaris_acl_sort(solaris_acl, count)) {
+ DEBUG(10, ("resulting acl is not valid!\n"));
+ goto done;
+ }
+
+ ret = acl(name, SETACL, count, solaris_acl);
+
+ done:
+ DEBUG(10, ("solarisacl_sys_acl_set_file %s.\n",
+ ((ret != 0) ? "failed" : "succeeded")));
+ SAFE_FREE(solaris_acl);
+ return ret;
+}
+
+/*
+ * set the access ACL on the file referred to by a fd
+ */
+int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ SOLARIS_ACL_T solaris_acl;
+ SOLARIS_ACL_T default_acl;
+ int count, default_count;
+ int ret = -1;
+
+ DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n"));
+
+ /*
+ * the posix acl_set_fd call sets the access acl of the
+ * file referred to by fd. the solaris facl-SETACL call
+ * sets the access and default acl as provided, so we
+ * have to retrieve the default acl of the file and
+ * concatenate it with the access acl provided.
+ */
+ if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count,
+ SMB_ACL_TYPE_ACCESS))
+ {
+ DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
+ strerror(errno)));
+ goto done;
+ }
+ if (!solaris_acl_get_fd(fd, &default_acl, &default_count)) {
+ DEBUG(10, ("error getting (default) acl from fd\n"));
+ goto done;
+ }
+ if (!solaris_add_to_acl(&solaris_acl, &count,
+ default_acl, default_count,
+ SMB_ACL_TYPE_DEFAULT))
+ {
+ DEBUG(10, ("error adding default acl to solaris acl\n"));
+ goto done;
+ }
+ if (!solaris_acl_sort(solaris_acl, count)) {
+ DEBUG(10, ("resulting acl is not valid!\n"));
+ goto done;
+ }
+
+ ret = facl(fd, SETACL, count, solaris_acl);
+ if (ret != 0) {
+ DEBUG(10, ("call of facl failed (%s).\n", strerror(errno)));
+ }
+
+ done:
+ DEBUG(10, ("solarisacl_sys_acl_st_fd %s.\n",
+ ((ret == 0) ? "succeded" : "failed" )));
+ SAFE_FREE(solaris_acl);
+ SAFE_FREE(default_acl);
+ return ret;
+}
+
+/*
+ * delete the default ACL of a directory
+ *
+ * This is achieved by fetching the access ACL and rewriting it
+ * directly, via the solaris system call: the SETACL call on
+ * directories writes both the access and the default ACL as provided.
+ *
+ * XXX: posix acl_delete_def_file returns an error if
+ * the file referred to by path is not a directory.
+ * this function does not complain but the actions
+ * have no effect on a file other than a directory.
+ * But sys_acl_delete_default_file is only called in
+ * smbd/posixacls.c after having checked that the file
+ * is a directory, anyways. So implementing the extra
+ * check is considered unnecessary. --- Agreed? XXX
+ */
+int solarisacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ SMB_ACL_T smb_acl;
+ int ret = -1;
+ SOLARIS_ACL_T solaris_acl;
+ int count;
+
+ DEBUG(10, ("entering solarisacl_sys_acl_delete_def_file.\n"));
+
+ smb_acl = solarisacl_sys_acl_get_file(handle, path,
+ SMB_ACL_TYPE_ACCESS);
+ if (smb_acl == NULL) {
+ DEBUG(10, ("getting file acl failed!\n"));
+ goto done;
+ }
+ if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count,
+ SMB_ACL_TYPE_ACCESS))
+ {
+ DEBUG(10, ("conversion smb_acl -> solaris_acl failed.\n"));
+ goto done;
+ }
+ if (!solaris_acl_sort(solaris_acl, count)) {
+ DEBUG(10, ("resulting acl is not valid!\n"));
+ goto done;
+ }
+ ret = acl(path, SETACL, count, solaris_acl);
+ if (ret != 0) {
+ DEBUG(10, ("settinge file acl failed!\n"));
+ }
+
+ done:
+ DEBUG(10, ("solarisacl_sys_acl_delete_def_file %s.\n",
+ ((ret != 0) ? "failed" : "succeeded" )));
+ SAFE_FREE(smb_acl);
+ return ret;
+}
+
+
+/* private functions */
+
+static SOLARIS_ACL_T solaris_acl_init(int count)
+{
+ SOLARIS_ACL_T solaris_acl =
+ (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count);
+ if (solaris_acl == NULL) {
+ errno = ENOMEM;
+ }
+ return solaris_acl;
+}
+
+/*
+ * Convert the SMB acl to the ACCESS or DEFAULT part of a
+ * solaris ACL, as desired.
+ */
+static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl,
+ SOLARIS_ACL_T *solaris_acl, int *count,
+ SMB_ACL_TYPE_T type)
+{
+ BOOL ret = False;
+ int i;
+ int check_which, check_rc;
+
+ DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
+
+ *solaris_acl = NULL;
+ *count = 0;
+
+ for (i = 0; i < smb_acl->count; i++) {
+ const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]);
+ SOLARIS_ACE_T solaris_entry;
+
+ ZERO_STRUCT(solaris_entry);
+
+ solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type);
+ if (solaris_entry.a_type == 0) {
+ DEBUG(10, ("smb_tag to solaris_tag failed\n"));
+ goto fail;
+ }
+ switch(solaris_entry.a_type) {
+ case USER:
+ DEBUG(10, ("got tag type USER with uid %d\n",
+ smb_entry->uid));
+ solaris_entry.a_id = (uid_t)smb_entry->uid;
+ break;
+ case GROUP:
+ DEBUG(10, ("got tag type GROUP with gid %d\n",
+ smb_entry->gid));
+ solaris_entry.a_id = (uid_t)smb_entry->gid;
+ break;
+ default:
+ break;
+ }
+ if (type == SMB_ACL_TYPE_DEFAULT) {
+ DEBUG(10, ("adding default bit to solaris ace\n"));
+ solaris_entry.a_type |= ACL_DEFAULT;
+ }
+
+ solaris_entry.a_perm =
+ smb_perm_to_solaris_perm(smb_entry->a_perm);
+ DEBUG(10, ("assembled the following solaris ace:\n"));
+ DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type));
+ DEBUGADD(10, (" - id: %d\n", solaris_entry.a_id));
+ DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm));
+ if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry,
+ 1, type))
+ {
+ DEBUG(10, ("error adding acl entry\n"));
+ goto fail;
+ }
+ DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i));
+ DEBUG(10, ("test, if entry has been copied into acl:\n"));
+ DEBUGADD(10, (" - type: 0x%04x\n",
+ (*solaris_acl)[(*count)-1].a_type));
+ DEBUGADD(10, (" - id: %d\n",
+ (*solaris_acl)[(*count)-1].a_id));
+ DEBUGADD(10, (" - perm: o%o\n",
+ (*solaris_acl)[(*count)-1].a_perm));
+ }
+
+ ret = True;
+ goto done;
+
+ fail:
+ SAFE_FREE(*solaris_acl);
+ done:
+ DEBUG(10, ("smb_acl_to_solaris_acl %s\n",
+ ((ret == True) ? "succeeded" : "failed")));
+ return ret;
+}
+
+/*
+ * convert either the access or the default part of a
+ * soaris acl to the SMB_ACL format.
+ */
+static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count,
+ SMB_ACL_TYPE_T type)
+{
+ SMB_ACL_T result;
+ int i;
+
+ if ((result = sys_acl_init(0)) == NULL) {
+ DEBUG(10, ("error allocating memory for SMB_ACL\n"));
+ goto fail;
+ }
+ for (i = 0; i < count; i++) {
+ SMB_ACL_ENTRY_T smb_entry;
+ SMB_ACL_PERM_T smb_perm;
+
+ if (!_IS_OF_TYPE(solaris_acl[i], type)) {
+ continue;
+ }
+ result = SMB_REALLOC(result,
+ sizeof(struct smb_acl_t) +
+ (sizeof(struct smb_acl_entry) *
+ (result->count + 1)));
+ if (result == NULL) {
+ DEBUG(10, ("error reallocating memory for SMB_ACL\n"));
+ goto fail;
+ }
+ smb_entry = &result->acl[result->count];
+ if (sys_acl_set_tag_type(smb_entry,
+ solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0)
+ {
+ DEBUG(10, ("invalid tag type given: 0x%04x\n",
+ solaris_acl[i].a_type));
+ goto fail;
+ }
+ /* intentionally not checking return code here: */
+ sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id);
+ smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm);
+ if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) {
+ DEBUG(10, ("invalid permset given: %d\n",
+ solaris_acl[i].a_perm));
+ goto fail;
+ }
+ result->count += 1;
+ }
+ goto done;
+
+ fail:
+ SAFE_FREE(result);
+ done:
+ DEBUG(10, ("solaris_acl_to_smb_acl %s\n",
+ ((result == NULL) ? "failed" : "succeeded")));
+ return result;
+}
+
+
+
+static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag)
+{
+ SOLARIS_ACL_TAG_T solaris_tag = 0;
+
+ DEBUG(10, ("smb_tag_to_solaris_tag\n"));
+ DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag));
+
+ switch (smb_tag) {
+ case SMB_ACL_USER:
+ solaris_tag = USER;
+ break;
+ case SMB_ACL_USER_OBJ:
+ solaris_tag = USER_OBJ;
+ break;
+ case SMB_ACL_GROUP:
+ solaris_tag = GROUP;
+ break;
+ case SMB_ACL_GROUP_OBJ:
+ solaris_tag = GROUP_OBJ;
+ break;
+ case SMB_ACL_OTHER:
+ solaris_tag = OTHER_OBJ;
+ break;
+ case SMB_ACL_MASK:
+ solaris_tag = CLASS_OBJ;
+ break;
+ default:
+ DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag));
+ break;
+ }
+
+ DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag));
+
+ return solaris_tag;
+}
+
+static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag)
+{
+ SMB_ACL_TAG_T smb_tag = 0;
+
+ DEBUG(10, ("solaris_tag_to_smb_tag:\n"));
+ DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag));
+
+ solaris_tag &= ~ACL_DEFAULT;
+
+ switch (solaris_tag) {
+ case USER:
+ smb_tag = SMB_ACL_USER;
+ break;
+ case USER_OBJ:
+ smb_tag = SMB_ACL_USER_OBJ;
+ break;
+ case GROUP:
+ smb_tag = SMB_ACL_GROUP;
+ break;
+ case GROUP_OBJ:
+ smb_tag = SMB_ACL_GROUP_OBJ;
+ break;
+ case OTHER_OBJ:
+ smb_tag = SMB_ACL_OTHER;
+ break;
+ case CLASS_OBJ:
+ smb_tag = SMB_ACL_MASK;
+ break;
+ default:
+ DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n",
+ solaris_tag));
+ break;
+ }
+
+ DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag));
+
+ return smb_tag;
+}
+
+
+static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm)
+{
+ SMB_ACL_PERM_T smb_perm = 0;
+ smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
+ smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
+ smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
+ return smb_perm;
+}
+
+
+static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm)
+{
+ SOLARIS_PERM_T solaris_perm = 0;
+ solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
+ solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
+ solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
+ return solaris_perm;
+}
+
+
+static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl,
+ int *count)
+{
+ BOOL result = False;
+
+ DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name));
+
+ /*
+ * The original code tries some INITIAL_ACL_SIZE
+ * and only did the GETACLCNT call upon failure
+ * (for performance reasons).
+ * For the sake of simplicity, I skip this for now.
+ */
+ *count = acl(name, GETACLCNT, 0, NULL);
+ if (*count < 0) {
+ DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno)));
+ goto done;
+ }
+ *solaris_acl = solaris_acl_init(*count);
+ if (*solaris_acl == NULL) {
+ DEBUG(10, ("error allocating memory for solaris acl...\n"));
+ goto done;
+ }
+ *count = acl(name, GETACL, *count, *solaris_acl);
+ if (*count < 0) {
+ DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno)));
+ goto done;
+ }
+ result = True;
+
+ done:
+ DEBUG(10, ("solaris_acl_get_file %s.\n",
+ ((result == True) ? "succeeded" : "failed" )));
+ return result;
+}
+
+
+static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count)
+{
+ BOOL ret = False;
+
+ DEBUG(10, ("entering solaris_acl_get_fd\n"));
+
+ /*
+ * see solaris_acl_get_file for comment about omission
+ * of INITIAL_ACL_SIZE...
+ */
+ *count = facl(fd, GETACLCNT, 0, NULL);
+ if (*count < 0) {
+ DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno)));
+ goto done;
+ }
+ *solaris_acl = solaris_acl_init(*count);
+ if (*solaris_acl == NULL) {
+ DEBUG(10, ("error allocating memory for solaris acl...\n"));
+ goto done;
+ }
+ *count = facl(fd, GETACL, *count, *solaris_acl);
+ if (*count < 0) {
+ DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno)));
+ goto done;
+ }
+ ret = True;
+
+ done:
+ DEBUG(10, ("solaris_acl_get_fd %s\n",
+ ((ret == True) ? "succeeded" : "failed")));
+ return ret;
+}
+
+
+
+/*
+ * Add entries to a solaris ACL.
+ *
+ * Entries are directly added to the solarisacl parameter.
+ * if memory allocation fails, this may result in solarisacl
+ * being NULL. if the resulting acl is to be checked and is
+ * not valid, it is kept in solarisacl but False is returned.
+ *
+ * The type of ACEs (access/default) to be added to the ACL can
+ * be selected via the type parameter.
+ * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS
+ * is defined as "0", this means that one can only add either
+ * access or default ACEs, not both at the same time. If it
+ * should become necessary to add all of an ACL, one would have
+ * to replace this parameter by another type.
+ */
+static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
+ SOLARIS_ACL_T add_acl, int add_count,
+ SMB_ACL_TYPE_T type)
+{
+ int i;
+
+ if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT))
+ {
+ DEBUG(10, ("invalid acl type given: %d\n", type));
+ errno = EINVAL;
+ return False;
+ }
+ for (i = 0; i < add_count; i++) {
+ if (!_IS_OF_TYPE(add_acl[i], type)) {
+ continue;
+ }
+ ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i],
+ solaris_acl, count);
+ if (solaris_acl == NULL) {
+ DEBUG(10, ("error enlarging acl.\n"));
+ errno = ENOMEM;
+ return False;
+ }
+ }
+ return True;
+}
+
+
+/*
+ * sort the ACL and check it for validity
+ *
+ * [original comment from lib/sysacls.c:]
+ *
+ * if it's a minimal ACL with only 4 entries then we
+ * need to recalculate the mask permissions to make
+ * sure that they are the same as the GROUP_OBJ
+ * permissions as required by the UnixWare acl() system call.
+ *
+ * (note: since POSIX allows minimal ACLs which only contain
+ * 3 entries - ie there is no mask entry - we should, in theory,
+ * check for this and add a mask entry if necessary - however
+ * we "know" that the caller of this interface always specifies
+ * a mask, so in practice "this never happens" (tm) - if it *does*
+ * happen aclsort() will fail and return an error and someone will
+ * have to fix it...)
+ */
+static BOOL solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
+{
+ int fixmask = (count <= 4);
+
+ if (aclsort(count, fixmask, solaris_acl) != 0) {
+ errno = EINVAL;
+ return False;
+ }
+ return True;
+}
+
+/*
+ * acl check function:
+ * unused at the moment but could be used to get more
+ * concrete error messages for debugging...
+ * (acl sort just says that the acl is invalid...)
+ */
+static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
+{
+ int check_rc;
+ int check_which;
+
+ check_rc = aclcheck(solaris_acl, count, &check_which);
+ if (check_rc != 0) {
+ DEBUG(10, ("acl is not valid:\n"));
+ DEBUGADD(10, (" - return code: %d\n", check_rc));
+ DEBUGADD(10, (" - which: %d\n", check_which));
+ if (check_which != -1) {
+ DEBUGADD(10, (" - invalid entry:\n"));
+ DEBUGADD(10, (" * type: %d:\n",
+ solaris_acl[check_which].a_type));
+ DEBUGADD(10, (" * id: %d\n",
+ solaris_acl[check_which].a_id));
+ DEBUGADD(10, (" * perm: 0o%o\n",
+ solaris_acl[check_which].a_perm));
+ }
+ return False;
+ }
+ return True;
+}
+
+
+/* VFS operations structure */
+
+static vfs_op_tuple solarisacl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(solarisacl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(solarisacl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(solarisacl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(solarisacl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(solarisacl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_solarisacl_init(void);
+NTSTATUS vfs_solarisacl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl",
+ solarisacl_op_tuples);
+}
+
+/* ENTE */
diff --git a/source/modules/vfs_tru64acl.c b/source/modules/vfs_tru64acl.c
new file mode 100644
index 00000000000..6aa9557c28c
--- /dev/null
+++ b/source/modules/vfs_tru64acl.c
@@ -0,0 +1,505 @@
+/*
+ Unix SMB/Netbios implementation.
+ VFS module to get and set Tru64 acls
+ Copyright (C) Michael Adam 2006
+
+ 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"
+
+/* prototypes for private functions first - for clarity */
+
+static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl);
+static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
+ struct smb_acl_entry *smb_ace);
+static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl);
+static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag);
+static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag);
+static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset);
+static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset);
+
+
+/* public functions - the api */
+
+SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle,
+ const char *path_p,
+ SMB_ACL_TYPE_T type)
+{
+ struct smb_acl_t *result;
+ acl_type_t the_acl_type;
+ acl_t tru64_acl;
+
+ DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n"));
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ the_acl_type = ACL_TYPE_ACCESS;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ the_acl_type = ACL_TYPE_DEFAULT;
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+
+ tru64_acl = acl_get_file((char *)path_p, the_acl_type);
+
+ if (tru64_acl == NULL) {
+ return NULL;
+ }
+
+ result = tru64_acl_to_smb_acl(tru64_acl);
+ acl_free(tru64_acl);
+ return result;
+}
+
+SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd)
+{
+ struct smb_acl_t *result;
+ acl_t tru64_acl = acl_get_fd(fd, ACL_TYPE_ACCESS);
+
+ if (tru64_acl == NULL) {
+ return NULL;
+ }
+
+ result = tru64_acl_to_smb_acl(tru64_acl);
+ acl_free(tru64_acl);
+ return result;
+}
+
+int tru64acl_sys_acl_set_file(vfs_handle_struct *handle,
+ const char *name,
+ SMB_ACL_TYPE_T type,
+ SMB_ACL_T theacl)
+{
+ int res;
+ acl_type_t the_acl_type;
+ acl_t tru64_acl;
+
+ DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n",
+ name, type));
+
+ switch(type) {
+ case SMB_ACL_TYPE_ACCESS:
+ DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n"));
+ the_acl_type = ACL_TYPE_ACCESS;
+ break;
+ case SMB_ACL_TYPE_DEFAULT:
+ DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n"));
+ the_acl_type = ACL_TYPE_DEFAULT;
+ break;
+ default:
+ DEBUGADD(10, ("invalid acl type\n"));
+ errno = EINVAL;
+ goto fail;
+ }
+
+ tru64_acl = smb_acl_to_tru64_acl(theacl);
+ if (tru64_acl == NULL) {
+ DEBUG(10, ("smb_acl_to_tru64_acl failed!\n"));
+ goto fail;
+ }
+ DEBUG(10, ("got tru64 acl...\n"));
+ res = acl_set_file((char *)name, the_acl_type, tru64_acl);
+ acl_free(tru64_acl);
+ if (res != 0) {
+ DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
+ goto fail;
+ }
+ return res;
+fail:
+ DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n"));
+ return -1;
+}
+
+int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ int fd, SMB_ACL_T theacl)
+{
+ int res;
+ acl_t tru64_acl = smb_acl_to_tru64_acl(theacl);
+ if (tru64_acl == NULL) {
+ return -1;
+ }
+ res = acl_set_fd(fd, ACL_TYPE_ACCESS, tru64_acl);
+ acl_free(tru64_acl);
+ return res;
+
+}
+
+int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle,
+ const char *path)
+{
+ return acl_delete_def_file((char *)path);
+}
+
+
+/* private functions */
+
+static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl)
+{
+ struct smb_acl_t *result;
+ acl_entry_t entry;
+
+ DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n"));
+
+ if ((result = SMB_MALLOC_P(struct smb_acl_t)) == NULL) {
+ DEBUG(0, ("SMB_MALLOC_P failed in tru64_acl_to_smb_acl\n"));
+ errno = ENOMEM;
+ goto fail;
+ }
+ ZERO_STRUCTP(result);
+ if (acl_first_entry((struct acl *)tru64_acl) != 0) {
+ DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno)));
+ goto fail;
+ }
+ while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) {
+ result = SMB_REALLOC(result, sizeof(struct smb_acl_t) +
+ (sizeof(struct smb_acl_entry) *
+ (result->count + 1)));
+ if (result == NULL) {
+ DEBUG(0, ("SMB_REALLOC failed in tru64_acl_to_smb_acl\n"));
+ errno = ENOMEM;
+ goto fail;
+ }
+ /* XYZ */
+ if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) {
+ SAFE_FREE(result);
+ goto fail;
+ }
+ result->count += 1;
+ }
+ return result;
+
+fail:
+ if (result != NULL) {
+ SAFE_FREE(result);
+ }
+ DEBUG(1, ("tru64_acl_to_smb_acl failed!\n"));
+ return NULL;
+}
+
+static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
+ struct smb_acl_entry *smb_ace)
+{
+ acl_tag_t tru64_tag;
+ acl_permset_t permset;
+ SMB_ACL_TAG_T smb_tag_type;
+ smb_acl_permset_t smb_permset;
+ void *qualifier;
+
+ if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) {
+ DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno)));
+ return False;
+ }
+
+ /* On could set the tag type directly to save a function call,
+ * but I like this better... */
+ smb_tag_type = tru64_tag_to_smb(tru64_tag);
+ if (smb_tag_type == 0) {
+ DEBUG(3, ("invalid tag type given: %d\n", tru64_tag));
+ return False;
+ }
+ if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) {
+ DEBUG(3, ("sys_acl_set_tag_type failed: %s\n",
+ strerror(errno)));
+ return False;
+ }
+ qualifier = acl_get_qualifier(tru64_ace);
+ if (qualifier != NULL) {
+ if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) {
+ DEBUG(3, ("sys_acl_set_qualifier failed\n"));
+ return False;
+ }
+ }
+ if (acl_get_permset(tru64_ace, &permset) != 0) {
+ DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno)));
+ return False;
+ }
+ smb_permset = tru64_permset_to_smb(*permset);
+ if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) {
+ DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno)));
+ return False;
+ }
+ return True;
+}
+
+static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl)
+{
+ acl_t result;
+ acl_entry_t tru64_entry;
+ int i;
+ char *acl_text;
+ ssize_t acl_text_len;
+
+ /* The tru64 acl_init function takes a size_t value
+ * instead of a count of entries (as with posix).
+ * the size parameter "Specifies the size of the working
+ * storage in bytes" (according to the man page).
+ * But it is unclear to me, how this size is to be
+ * calculated.
+ *
+ * It should not matter, since acl_create_entry enlarges
+ * the working storage at need. ... */
+
+ DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n"));
+
+ result = acl_init(1);
+
+ if (result == NULL) {
+ DEBUG(3, ("acl_init failed!\n"));
+ goto fail;
+ }
+
+ DEBUGADD(10, ("parsing acl entries...\n"));
+ for (i = 0; i < smb_acl->count; i++) {
+ /* XYZ - maybe eliminate this direct access? */
+ const struct smb_acl_entry *smb_entry = &smb_acl->acl[i];
+ acl_tag_t tru64_tag;
+ acl_perm_t tru64_permset;
+
+ tru64_tag = smb_tag_to_tru64(smb_entry->a_type);
+ if (tru64_tag == -1) {
+ DEBUG(3, ("smb_tag_to_tru64 failed!\n"));
+ goto fail;
+ }
+
+ if (tru64_tag == ACL_MASK) {
+ DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n"));
+ continue;
+ }
+
+ tru64_entry = acl_create_entry(&result);
+ if (tru64_entry == NULL) {
+ DEBUG(3, ("acl_create_entry failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+
+ if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) {
+ DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+
+ switch (smb_entry->a_type) {
+ case SMB_ACL_USER:
+ if (acl_set_qualifier(tru64_entry,
+ (int *)&smb_entry->uid) != 0)
+ {
+ DEBUG(3, ("acl_set_qualifier failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+ DEBUGADD(10, (" - setting uid to %d\n", smb_entry->uid));
+ break;
+ case SMB_ACL_GROUP:
+ if (acl_set_qualifier(tru64_entry,
+ (int *)&smb_entry->gid) != 0)
+ {
+ DEBUG(3, ("acl_set_qualifier failed: %s\n",
+ strerror(errno)));
+ goto fail;
+ }
+ DEBUGADD(10, (" - setting gid to %d\n", smb_entry->gid));
+ break;
+ default:
+ break;
+ }
+
+ tru64_permset = smb_permset_to_tru64(smb_entry->a_perm);
+ if (tru64_permset == -1) {
+ DEBUG(3, ("smb_permset_to_tru64 failed!\n"));
+ goto fail;
+ }
+ DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset));
+ if (acl_set_permset(tru64_entry, &tru64_permset) != 0)
+ {
+ DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno)));
+ goto fail;
+ }
+ } /* for */
+ DEBUGADD(10, ("done parsing acl entries\n"));
+
+ tru64_entry = NULL;
+ if (acl_valid(result, &tru64_entry) != 0) {
+ DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n",
+ strerror(errno)));
+ if (tru64_entry != NULL) {
+ DEBUGADD(1, ("the acl contains duplicate entries\n"));
+ }
+ goto fail;
+ }
+ DEBUGADD(10, ("acl is valid\n"));
+
+ acl_text = acl_to_text(result, &acl_text_len);
+ if (acl_text == NULL) {
+ DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno)));
+ goto fail;
+ }
+ DEBUG(1, ("acl_text: %s\n", acl_text));
+ free(acl_text);
+
+ return result;
+
+fail:
+ if (result != NULL) {
+ acl_free(result);
+ }
+ DEBUG(1, ("smb_acl_to_tru64_acl failed!\n"));
+ return NULL;
+}
+
+static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag)
+{
+ acl_tag_t result;
+ switch (smb_tag) {
+ case SMB_ACL_USER:
+ result = ACL_USER;
+ DEBUGADD(10, ("got acl type ACL_USER\n"));
+ break;
+ case SMB_ACL_USER_OBJ:
+ result = ACL_USER_OBJ;
+ DEBUGADD(10, ("got acl type ACL_USER_OBJ\n"));
+ break;
+ case SMB_ACL_GROUP:
+ result = ACL_GROUP;
+ DEBUGADD(10, ("got acl type ACL_GROUP\n"));
+ break;
+ case SMB_ACL_GROUP_OBJ:
+ result = ACL_GROUP_OBJ;
+ DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n"));
+ break;
+ case SMB_ACL_OTHER:
+ result = ACL_OTHER;
+ DEBUGADD(10, ("got acl type ACL_OTHER\n"));
+ break;
+ case SMB_ACL_MASK:
+ result = ACL_MASK;
+ DEBUGADD(10, ("got acl type ACL_MASK\n"));
+ break;
+ default:
+ DEBUG(1, ("Unknown tag type %d\n", smb_tag));
+ result = -1;
+ }
+ return result;
+}
+
+
+static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag)
+{
+ SMB_ACL_TAG_T smb_tag_type;
+ switch(tru64_tag) {
+ case ACL_USER:
+ smb_tag_type = SMB_ACL_USER;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n"));
+ break;
+ case ACL_USER_OBJ:
+ smb_tag_type = SMB_ACL_USER_OBJ;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n"));
+ break;
+ case ACL_GROUP:
+ smb_tag_type = SMB_ACL_GROUP;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n"));
+ break;
+ case ACL_GROUP_OBJ:
+ smb_tag_type = SMB_ACL_GROUP_OBJ;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n"));
+ break;
+ case ACL_OTHER:
+ smb_tag_type = SMB_ACL_OTHER;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n"));
+ break;
+ case ACL_MASK:
+ smb_tag_type = SMB_ACL_MASK;
+ DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n"));
+ break;
+ default:
+ DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag));
+ smb_tag_type = 0;
+ }
+ return smb_tag_type;
+}
+
+static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset)
+{
+ /* originally, I thought that acl_clear_perm was the
+ * proper way to reset the permset to 0. but without
+ * initializing it to 0, acl_clear_perm fails.
+ * so probably, acl_clear_perm is not necessary here... ?! */
+ acl_perm_t tru64_permset = 0;
+ if (acl_clear_perm(&tru64_permset) != 0) {
+ DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno)));
+ return -1;
+ }
+ /* according to original lib/sysacls.c, acl_add_perm is
+ * broken on tru64 ... */
+ tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0);
+ tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0);
+ tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0);
+ return tru64_permset;
+}
+
+static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset)
+{
+ smb_acl_permset_t smb_permset = 0;
+ smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0);
+ smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0);
+ smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
+ return smb_permset;
+}
+
+
+/* VFS operations structure */
+
+static vfs_op_tuple tru64acl_op_tuples[] = {
+ /* Disk operations */
+ {SMB_VFS_OP(tru64acl_sys_acl_get_file),
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(tru64acl_sys_acl_get_fd),
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(tru64acl_sys_acl_set_file),
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(tru64acl_sys_acl_set_fd),
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(tru64acl_sys_acl_delete_def_file),
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_LAYER_TRANSPARENT},
+
+ {SMB_VFS_OP(NULL),
+ SMB_VFS_OP_NOOP,
+ SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_tru64acl_init(void);
+NTSTATUS vfs_tru64acl_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl",
+ tru64acl_op_tuples);
+}
+
+/* ENTE */
diff --git a/source/modules/weird.c b/source/modules/weird.c
index ccee9d71edd..12a535cbb75 100644
--- a/source/modules/weird.c
+++ b/source/modules/weird.c
@@ -125,6 +125,7 @@ static size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft,
struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push};
+NTSTATUS charset_weird_init(void);
NTSTATUS charset_weird_init(void)
{
return smb_register_charset(&weird_functions);
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 26495d25c13..46f209872b0 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -77,7 +77,7 @@ static void terminate(void)
**************************************************************************** */
static void nmbd_terminate(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
terminate();
}
@@ -112,9 +112,7 @@ static void sig_hup(int sig)
static void fault_continue(void)
{
-#if DUMP_CORE
dump_core();
-#endif
}
/**************************************************************************** **
@@ -274,7 +272,7 @@ static BOOL reload_nmbd_services(BOOL test)
**************************************************************************** */
static void msg_reload_nmbd_services(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
write_browse_list( 0, True );
dump_all_namelists();
@@ -291,7 +289,7 @@ static void msg_reload_nmbd_services(int msg_type, struct process_id src,
}
static void msg_nmbd_send_packet(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
struct packet_struct *p = (struct packet_struct *)buf;
struct subnet_record *subrec;
@@ -560,7 +558,7 @@ static void process(void)
if(reload_after_sighup) {
DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
- pid_to_procid(0), (void*) &no_subnets, 0);
+ pid_to_procid(0), (void*) &no_subnets, 0, NULL);
if(no_subnets)
return;
reload_after_sighup = 0;
@@ -747,14 +745,14 @@ static BOOL open_sockets(BOOL isdaemon, int port)
pidfile_create("nmbd");
message_init();
- message_register(MSG_FORCE_ELECTION, nmbd_message_election);
+ message_register(MSG_FORCE_ELECTION, nmbd_message_election, NULL);
#if 0
/* Until winsrepl is done. */
- message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
+ message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry, NULL);
#endif
- message_register(MSG_SHUTDOWN, nmbd_terminate);
- message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
- message_register(MSG_SEND_PACKET, msg_nmbd_send_packet);
+ message_register(MSG_SHUTDOWN, nmbd_terminate, NULL);
+ message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services, NULL);
+ message_register(MSG_SEND_PACKET, msg_nmbd_send_packet, NULL);
TimeInit();
diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c
index e27e483702a..b75028be0db 100644
--- a/source/nmbd/nmbd_browserdb.c
+++ b/source/nmbd/nmbd_browserdb.c
@@ -86,7 +86,6 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
struct in_addr ip )
{
struct browse_cache_record *browc;
- struct browse_cache_record *tmp_browc;
time_t now = time( NULL );
browc = SMB_MALLOC_P(struct browse_cache_record);
@@ -115,7 +114,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
browc->ip = ip;
- DLIST_ADD_END(lmb_browserlist, browc, tmp_browc);
+ DLIST_ADD_END(lmb_browserlist, browc, struct browse_cache_record *);
if( DEBUGLVL( 3 ) ) {
Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" );
diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c
index 50e13729361..3aadd70b83c 100644
--- a/source/nmbd/nmbd_elections.c
+++ b/source/nmbd/nmbd_elections.c
@@ -379,7 +379,7 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
***************************************************************************/
void nmbd_message_election(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
struct subnet_record *subrec;
diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c
index 5c0fc2c521c..4a8d1db51db 100644
--- a/source/nmbd/nmbd_processlogon.c
+++ b/source/nmbd/nmbd_processlogon.c
@@ -382,7 +382,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
}
#ifdef HAVE_ADS
else {
- struct uuid domain_guid;
+ struct GUID domain_guid;
UUID_FLAT flat_guid;
pstring domain;
pstring hostname;
diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c
index 28ad92ed108..7fe39676c6f 100644
--- a/source/nmbd/nmbd_synclists.c
+++ b/source/nmbd/nmbd_synclists.c
@@ -68,7 +68,7 @@ static void sync_child(char *name, int nm_type,
char *fname)
{
fstring unix_workgroup;
- static struct cli_state cli;
+ struct cli_state *cli;
uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
struct nmb_name called, calling;
@@ -76,50 +76,56 @@ static void sync_child(char *name, int nm_type,
* Patch from Andy Levine andyl@epicrealm.com.
*/
- if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) {
+ cli = cli_initialise();
+ if (!cli) {
+ return;
+ }
+
+ if (!cli_set_port(cli, 139) || !cli_connect(cli, name, &ip)) {
return;
}
make_nmb_name(&calling, local_machine, 0x0);
make_nmb_name(&called , name, nm_type);
- if (!cli_session_request(&cli, &calling, &called)) {
- cli_shutdown(&cli);
+ if (!cli_session_request(cli, &calling, &called)) {
+ cli_shutdown(cli);
return;
}
- if (!cli_negprot(&cli)) {
- cli_shutdown(&cli);
+ if (!cli_negprot(cli)) {
+ cli_shutdown(cli);
return;
}
- if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) {
- cli_shutdown(&cli);
+ if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 1, "", 0,
+ workgroup))) {
+ cli_shutdown(cli);
return;
}
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
- cli_shutdown(&cli);
+ if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
+ cli_shutdown(cli);
return;
}
/* All the cli_XX functions take UNIX character set. */
- fstrcpy(unix_workgroup, cli.server_domain?cli.server_domain:workgroup);
+ fstrcpy(unix_workgroup, cli->server_domain ? cli->server_domain : workgroup);
/* Fetch a workgroup list. */
- cli_NetServerEnum(&cli, unix_workgroup,
+ cli_NetServerEnum(cli, unix_workgroup,
local_type|SV_TYPE_DOMAIN_ENUM,
callback, NULL);
/* Now fetch a server list. */
if (servers) {
fstrcpy(unix_workgroup, workgroup);
- cli_NetServerEnum(&cli, unix_workgroup,
+ cli_NetServerEnum(cli, unix_workgroup,
local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
callback, NULL);
}
- cli_shutdown(&cli);
+ cli_shutdown(cli);
}
/*******************************************************************
diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
index 75841414bc4..6ea102c3913 100644
--- a/source/nmbd/nmbd_winsserver.c
+++ b/source/nmbd/nmbd_winsserver.c
@@ -159,7 +159,7 @@ static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
len = (2 + 1 + (7*4)); /* "wbddddddd" */
len += (namerec->data.num_ips * 4);
- data.dptr = SMB_MALLOC(len);
+ data.dptr = (char *)SMB_MALLOC(len);
if (!data.dptr) {
return data;
}
@@ -2371,7 +2371,7 @@ void wins_write_database(time_t t, BOOL background)
***************************************************************************/
void nmbd_wins_new_entry(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
WINS_RECORD *record;
struct name_record *namerec = NULL;
diff --git a/source/nsswitch/idmap.c b/source/nsswitch/idmap.c
new file mode 100644
index 00000000000..d69fd68e103
--- /dev/null
+++ b/source/nsswitch/idmap.c
@@ -0,0 +1,1310 @@
+/*
+ Unix SMB/CIFS implementation.
+ ID Mapping
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Simo Sorce 2003
+ Copyright (C) Jeremy Allison 2006
+
+ 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 "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+static_decl_idmap;
+
+struct idmap_backend {
+ const char *name;
+ struct idmap_methods *methods;
+ struct idmap_backend *prev, *next;
+};
+
+struct idmap_alloc_backend {
+ const char *name;
+ struct idmap_alloc_methods *methods;
+ struct idmap_alloc_backend *prev, *next;
+};
+
+struct idmap_cache_ctx;
+
+static TALLOC_CTX *idmap_ctx = NULL;
+static struct idmap_cache_ctx *idmap_cache;
+
+static struct idmap_backend *backends = NULL;
+static struct idmap_domain **idmap_domains = NULL;
+static int num_domains = 0;
+static int pdb_dom_num = -1;
+static int def_dom_num = -1;
+
+static struct idmap_alloc_backend *alloc_backends = NULL;
+static struct idmap_alloc_methods *alloc_methods = NULL;
+
+#define IDMAP_CHECK_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); goto done; } } while(0)
+#define IDMAP_CHECK_ALLOC(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while(0)
+
+static struct idmap_methods *get_methods(struct idmap_backend *be, const char *name)
+{
+ struct idmap_backend *b;
+
+ for (b = be; b; b = b->next) {
+ if (strequal(b->name, name)) {
+ return b->methods;
+ }
+ }
+
+ return NULL;
+}
+
+static struct idmap_alloc_methods *get_alloc_methods(struct idmap_alloc_backend *be, const char *name)
+{
+ struct idmap_alloc_backend *b;
+
+ for (b = be; b; b = b->next) {
+ if (strequal(b->name, name)) {
+ return b->methods;
+ }
+ }
+
+ return NULL;
+}
+
+/**********************************************************************
+ Allow a module to register itself as a method.
+**********************************************************************/
+
+NTSTATUS smb_register_idmap(int version, const char *name, struct idmap_methods *methods)
+{
+ struct idmap_methods *test;
+ struct idmap_backend *entry;
+
+ if (!idmap_ctx) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
+ DEBUG(0, ("Failed to register idmap module.\n"
+ "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n"
+ "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
+ "Please recompile against the current version of samba!\n",
+ version, SMB_IDMAP_INTERFACE_VERSION));
+ return NT_STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ if (!name || !name[0] || !methods) {
+ DEBUG(0,("Called with NULL pointer or empty name!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ test = get_methods(backends, name);
+ if (test) {
+ DEBUG(0,("Idmap module %s already registered!\n", name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ entry = talloc(idmap_ctx, struct idmap_backend);
+ if ( ! entry) {
+ DEBUG(0,("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ entry->name = talloc_strdup(idmap_ctx, name);
+ if ( ! entry->name) {
+ DEBUG(0,("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ entry->methods = methods;
+
+ DLIST_ADD(backends, entry);
+ DEBUG(5, ("Successfully added idmap backend '%s'\n", name));
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Allow a module to register itself as a method.
+**********************************************************************/
+
+NTSTATUS smb_register_idmap_alloc(int version, const char *name, struct idmap_alloc_methods *methods)
+{
+ struct idmap_alloc_methods *test;
+ struct idmap_alloc_backend *entry;
+
+ if (!idmap_ctx) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
+ DEBUG(0, ("Failed to register idmap alloc module.\n"
+ "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n"
+ "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
+ "Please recompile against the current version of samba!\n",
+ version, SMB_IDMAP_INTERFACE_VERSION));
+ return NT_STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ if (!name || !name[0] || !methods) {
+ DEBUG(0,("Called with NULL pointer or empty name!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ test = get_alloc_methods(alloc_backends, name);
+ if (test) {
+ DEBUG(0,("idmap_alloc module %s already registered!\n", name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ entry = talloc(idmap_ctx, struct idmap_alloc_backend);
+ if ( ! entry) {
+ DEBUG(0,("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ entry->name = talloc_strdup(idmap_ctx, name);
+ if ( ! entry->name) {
+ DEBUG(0,("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ entry->methods = methods;
+
+ DLIST_ADD(alloc_backends, entry);
+ DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name));
+ return NT_STATUS_OK;
+}
+
+static int close_domain_destructor(struct idmap_domain *dom)
+{
+ NTSTATUS ret;
+
+ ret = dom->methods->close_fn(dom);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(3, ("Failed to close idmap domain [%s]!\n", dom->name));
+ }
+
+ return 0;
+}
+
+/**************************************************************************
+ Shutdown.
+**************************************************************************/
+
+NTSTATUS idmap_close(void)
+{
+ /* close the alloc backend first before freeing idmap_ctx */
+ if (alloc_methods) {
+ alloc_methods->close_fn();
+ alloc_methods = NULL;
+ }
+ alloc_backends = NULL;
+
+ /* this talloc_free call will fire the talloc destructors
+ * that will free all active backends resources */
+ TALLOC_FREE(idmap_ctx);
+ idmap_cache = NULL;
+ idmap_domains = NULL;
+ backends = NULL;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Initialise idmap cache and a remote backend (if configured).
+**********************************************************************/
+
+static const char *idmap_default_domain[] = { "default domain", NULL };
+
+NTSTATUS idmap_init(void)
+{
+ NTSTATUS ret;
+ struct idmap_domain *dom;
+ char *compat_backend = NULL;
+ char *compat_params = NULL;
+ const char **dom_list = NULL;
+ char *alloc_backend;
+ BOOL default_already_defined = False;
+ BOOL pri_dom_is_in_list = False;
+ int compat = 0;
+ int i;
+
+ if (idmap_ctx) {
+ return NT_STATUS_OK;
+ }
+
+ if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ static_init_idmap;
+
+ dom_list = lp_idmap_domains();
+
+ if ( dom_list && lp_idmap_backend() ) {
+ DEBUG(0, ("WARNING: idmap backend and idmap domains are "
+ "mutually excusive!\n"));
+ DEBUGADD(0,("idmap backend option will be IGNORED!\n"));
+ } else if ( lp_idmap_backend() ) {
+ const char **compat_list = lp_idmap_backend();
+ char *p = NULL;
+ const char *q = NULL;
+
+ DEBUG(0, ("WARNING: idmap backend is deprecated!\n"));
+ compat = 1;
+
+ if ( (compat_backend = talloc_strdup( idmap_ctx, *compat_list )) == NULL ) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* strip any leading idmap_ prefix of */
+ if (strncmp(*compat_list, "idmap_", 6) == 0 ) {
+ q = *compat_list += 6;
+ DEBUG(0, ("WARNING: idmap backend uses obsolete and "
+ "deprecated 'idmap_' prefix.\n"
+ "Please replace 'idmap_%s' by '%s' in %s\n",
+ q, q, dyn_CONFIGFILE));
+ compat_backend = talloc_strdup( idmap_ctx, q);
+ } else {
+ compat_backend = talloc_strdup( idmap_ctx, *compat_list);
+ }
+
+ /* separate the backend and module arguements */
+ if ((p = strchr(compat_backend, ':')) != NULL) {
+ *p = '\0';
+ compat_params = p + 1;
+ }
+ }
+
+ if ( ! dom_list) {
+ dom_list = idmap_default_domain;
+ }
+
+ /***************************
+ * initialize idmap domains
+ */
+ DEBUG(1, ("Initializing idmap domains\n"));
+
+ for (i = 0; dom_list[i]; i++) {
+ const char *parm_backend;
+ char *config_option;
+
+ if (strequal(dom_list[i], lp_workgroup())) {
+ pri_dom_is_in_list = True;
+ }
+ /* init domain */
+
+ dom = talloc_zero(idmap_ctx, struct idmap_domain);
+ IDMAP_CHECK_ALLOC(dom);
+
+ dom->name = talloc_strdup(dom, dom_list[i]);
+ IDMAP_CHECK_ALLOC(dom->name);
+
+ config_option = talloc_asprintf(dom, "idmap config %s", dom->name);
+ IDMAP_CHECK_ALLOC(config_option);
+
+ /* default or specific ? */
+
+ dom->default_domain = lp_parm_bool(-1, config_option, "default", False);
+
+ if (dom->default_domain ||
+ strequal(dom_list[i], idmap_default_domain[0])) {
+
+ /* make sure this is set even when we match idmap_default_domain[0] */
+ dom->default_domain = True;
+
+ if (default_already_defined) {
+ DEBUG(1, ("ERROR: Multiple domains defined as default!\n"));
+ ret = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+
+ default_already_defined = True;
+
+ }
+
+ dom->readonly = lp_parm_bool(-1, config_option, "readonly", False);
+
+ /* find associated backend (default: tdb) */
+ if (compat) {
+ parm_backend = talloc_strdup(idmap_ctx, compat_backend);
+ } else {
+ parm_backend = talloc_strdup(idmap_ctx,
+ lp_parm_const_string(-1, config_option, "backend", "tdb"));
+ }
+ IDMAP_CHECK_ALLOC(parm_backend);
+
+ /* get the backend methods for this domain */
+ dom->methods = get_methods(backends, parm_backend);
+
+ if ( ! dom->methods) {
+ ret = smb_probe_module("idmap", parm_backend);
+ if (NT_STATUS_IS_OK(ret)) {
+ dom->methods = get_methods(backends, parm_backend);
+ }
+ }
+ if ( ! dom->methods) {
+ DEBUG(0, ("ERROR: Could not get methods for backend %s\n", parm_backend));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* check the set_mapping function exists otherwise mark the module as readonly */
+ if ( ! dom->methods->set_mapping) {
+ dom->readonly = True;
+ }
+
+ /* now that we have methods, set the destructor for this domain */
+ talloc_set_destructor(dom, close_domain_destructor);
+
+ /* Finally instance a backend copy for this domain */
+ ret = dom->methods->init(dom, compat_params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s)\n",
+ parm_backend, dom->name));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, i+1);
+ if ( ! idmap_domains) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ idmap_domains[i] = dom;
+
+ if (dom->default_domain) { /* save default domain position for future uses */
+ def_dom_num = i;
+ }
+
+ DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n",
+ dom->name, parm_backend,
+ dom->default_domain?"":"not ", dom->readonly?"":"not "));
+
+ talloc_free(config_option);
+ }
+
+ /* save the number of domains we have */
+ num_domains = i;
+
+ /* automatically add idmap_nss backend if needed */
+ if ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
+ ( ! pri_dom_is_in_list) &&
+ lp_winbind_trusted_domains_only()) {
+
+ dom = talloc_zero(idmap_ctx, struct idmap_domain);
+ IDMAP_CHECK_ALLOC(dom);
+
+ dom->name = talloc_strdup(dom, lp_workgroup());
+ IDMAP_CHECK_ALLOC(dom->name);
+
+ dom->default_domain = False;
+ dom->readonly = True;
+
+ /* get the backend methods for passdb */
+ dom->methods = get_methods(backends, "nss");
+
+ /* (the nss module is always statically linked) */
+ if ( ! dom->methods) {
+ DEBUG(0, ("ERROR: Could not get methods for idmap_nss ?!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* now that we have methods, set the destructor for this domain */
+ talloc_set_destructor(dom, close_domain_destructor);
+
+ /* Finally instance a backend copy for this domain */
+ ret = dom->methods->init(dom, compat_params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for idmap_nss ?!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, num_domains+1);
+ if ( ! idmap_domains) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ idmap_domains[num_domains] = dom;
+
+ DEBUG(10, ("Domain %s - Backend nss - not default - readonly\n", dom->name ));
+
+ num_domains++;
+ }
+
+ /**** automatically add idmap_passdb backend ****/
+ dom = talloc_zero(idmap_ctx, struct idmap_domain);
+ IDMAP_CHECK_ALLOC(dom);
+
+ dom->name = talloc_strdup(dom, get_global_sam_name());
+ IDMAP_CHECK_ALLOC(dom->name);
+
+ dom->default_domain = False;
+ dom->readonly = True;
+
+ /* get the backend methods for passdb */
+ dom->methods = get_methods(backends, "passdb");
+
+ /* (the passdb module is always statically linked) */
+ if ( ! dom->methods) {
+ DEBUG(0, ("ERROR: Could not get methods for idmap_passdb ?!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* now that we have methods, set the destructor for this domain */
+ talloc_set_destructor(dom, close_domain_destructor);
+
+ /* Finally instance a backend copy for this domain */
+ ret = dom->methods->init(dom, compat_params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for idmap_passdb ?!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, num_domains+1);
+ if ( ! idmap_domains) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ idmap_domains[num_domains] = dom;
+
+ /* needed to handle special BUILTIN and wellknown SIDs cases */
+ pdb_dom_num = num_domains;
+
+ DEBUG(10, ("Domain %s - Backend passdb - not default - readonly\n", dom->name));
+
+ num_domains++;
+ /**** finished adding idmap_passdb backend ****/
+
+ /* sort domains so that the default is the last one */
+ /* don't sort if no default domain defined */
+ if (def_dom_num != -1 && def_dom_num != num_domains-1) { /* default is not last, move it */
+ struct idmap_domain *tmp;
+
+ if (pdb_dom_num > def_dom_num) {
+ pdb_dom_num --;
+
+ } else if (pdb_dom_num == def_dom_num) { /* ?? */
+ pdb_dom_num = num_domains - 1;
+ }
+
+ tmp = idmap_domains[def_dom_num];
+
+ for (i = def_dom_num; i < num_domains-1; i++) {
+ idmap_domains[i] = idmap_domains[i+1];
+ }
+ idmap_domains[i] = tmp;
+ def_dom_num = i;
+ }
+
+
+ /***************************
+ * initialize alloc module
+ */
+ DEBUG(1, ("Initializing idmap alloc module\n"));
+
+ if (compat) {
+ alloc_backend = talloc_strdup(idmap_ctx, compat_backend);
+ } else {
+ char *ab = lp_idmap_alloc_backend();
+
+ if (ab && (ab[0] != '\0')) {
+ alloc_backend = talloc_strdup(idmap_ctx, lp_idmap_alloc_backend());
+ } else {
+ alloc_backend = talloc_strdup(idmap_ctx, "tdb");
+ }
+ }
+ IDMAP_CHECK_ALLOC(alloc_backend);
+
+ alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
+ if ( ! alloc_methods) {
+ ret = smb_probe_module("idmap", alloc_backend);
+ if (NT_STATUS_IS_OK(ret)) {
+ alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
+ }
+ }
+ if ( ! alloc_methods) {
+ DEBUG(0, ("ERROR: Could not get methods for alloc backend %s\n", alloc_backend));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ ret = alloc_methods->init(compat_params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for alloc backend %s\n", alloc_backend));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* cleanpu temporary strings */
+ TALLOC_FREE( compat_backend );
+
+ return NT_STATUS_OK;
+
+done:
+ DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
+ idmap_close();
+ return ret;
+}
+
+/**************************************************************************
+ idmap allocator interface functions
+**************************************************************************/
+
+NTSTATUS idmap_allocate_uid(struct unixid *id)
+{
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ id->type = ID_TYPE_UID;
+ return alloc_methods->allocate_id(id);
+}
+
+NTSTATUS idmap_allocate_gid(struct unixid *id)
+{
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ id->type = ID_TYPE_GID;
+ return alloc_methods->allocate_id(id);
+}
+
+NTSTATUS idmap_set_uid_hwm(struct unixid *id)
+{
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ id->type = ID_TYPE_UID;
+ return alloc_methods->set_id_hwm(id);
+}
+
+NTSTATUS idmap_set_gid_hwm(struct unixid *id)
+{
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ id->type = ID_TYPE_GID;
+ return alloc_methods->set_id_hwm(id);
+}
+
+/******************************************************************************
+ Lookup an idmap_domain give a full user or group SID
+ ******************************************************************************/
+
+static struct idmap_domain* find_idmap_domain_from_sid( DOM_SID *account_sid )
+{
+ DOM_SID domain_sid;
+ uint32 rid;
+ struct winbindd_domain *domain = NULL;
+ int i;
+
+ /* 1. Handle BUILTIN or Special SIDs and prevent them from
+ falling into the default domain space (if we have a
+ configured passdb backend. */
+
+ if ( (pdb_dom_num != -1) &&
+ (sid_check_is_in_builtin(account_sid) ||
+ sid_check_is_in_wellknown_domain(account_sid)) )
+ {
+ return idmap_domains[pdb_dom_num];
+ }
+
+ /* 2. Lookup the winbindd_domain from the account_sid */
+
+ sid_copy( &domain_sid, account_sid );
+ sid_split_rid( &domain_sid, &rid );
+ domain = find_domain_from_sid_noinit( &domain_sid );
+
+ for (i = 0; domain && i < num_domains; i++) {
+ if ( strequal( idmap_domains[i]->name, domain->name ) ) {
+ return idmap_domains[i];
+ }
+ }
+
+ /* 3. Fall back to the default domain */
+
+ if ( def_dom_num != -1 ) {
+ return idmap_domains[def_dom_num];
+ }
+
+ return NULL;
+}
+
+/******************************************************************************
+ Lookup an index given an idmap_domain pointer
+ ******************************************************************************/
+
+static uint32 find_idmap_domain_index( struct idmap_domain *id_domain)
+{
+ int i;
+
+ for (i = 0; i < num_domains; i++) {
+ if ( idmap_domains[i] == id_domain )
+ return i;
+ }
+
+ return -1;
+}
+
+
+/*********************************************************
+ Check if creating a mapping is permitted for the domain
+*********************************************************/
+
+static NTSTATUS idmap_can_map(const struct id_map *map, struct idmap_domain **ret_dom)
+{
+ struct idmap_domain *dom;
+
+ /* Check we do not create mappings for our own local domain, or BUILTIN or special SIDs */
+ if ((sid_compare_domain(map->sid, get_global_sam_sid()) == 0) ||
+ sid_check_is_in_builtin(map->sid) ||
+ sid_check_is_in_wellknown_domain(map->sid)) {
+ DEBUG(10, ("We are not supposed to create mappings for our own domains (local, builtin, specials)\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Special check for trusted domain only = Yes */
+ if (lp_winbind_trusted_domains_only()) {
+ struct winbindd_domain *wdom = find_our_domain();
+ if (wdom && (sid_compare_domain(map->sid, &wdom->sid) == 0)) {
+ DEBUG(10, ("We are not supposed to create mappings for our primary domain when <trusted domain only> is True\n"));
+ DEBUGADD(10, ("Leave [%s] unmapped\n", sid_string_static(map->sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) {
+ /* huh, couldn't find a suitable domain, let's just leave it unmapped */
+ DEBUG(10, ("Could not find idmap backend for SID %s", sid_string_static(map->sid)));
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ if (dom->readonly) {
+ /* ouch the domain is read only, let's just leave it unmapped */
+ DEBUG(10, ("idmap backend for SID %s is READONLY!\n", sid_string_static(map->sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *ret_dom = dom;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ struct idmap_domain *dom;
+ const char *domname, *name;
+ enum lsa_SidType sid_type;
+ BOOL wbret;
+
+ ret = idmap_can_map(map, &dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ /* by default calls to winbindd are disabled
+ the following call will not recurse so this is safe */
+ winbind_on();
+ wbret = winbind_lookup_sid(ctx, map->sid, &domname, &name, &sid_type);
+ winbind_off();
+
+ /* check if this is a valid SID and then map it */
+ if (wbret) {
+ switch (sid_type) {
+ case SID_NAME_USER:
+ ret = idmap_allocate_uid(&map->xid);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* can't allocate id, let's just leave it unmapped */
+ DEBUG(2, ("uid allocation failed! Can't create mapping\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ break;
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ ret = idmap_allocate_gid(&map->xid);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* can't allocate id, let's just leave it unmapped */
+ DEBUG(2, ("gid allocation failed! Can't create mapping\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ break;
+ default:
+ /* invalid sid, let's just leave it unmapped */
+ DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ /* ok, got a new id, let's set a mapping */
+ map->status = ID_MAPPED;
+
+ DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
+ sid_string_static(map->sid),
+ (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
+ (unsigned long)map->xid.id));
+ ret = dom->methods->set_mapping(dom, map);
+
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* something wrong here :-( */
+ DEBUG(2, ("Failed to commit mapping\n!"));
+
+ /* TODO: would it make sense to have an "unalloc_id function?" */
+
+ return NT_STATUS_NONE_MAPPED;
+ }
+ } else {
+ DEBUG(2,("Invalid SID, not mapping %s (type %d)\n",
+ sid_string_static(map->sid), sid_type));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS idmap_backends_set_mapping(const struct id_map *map)
+{
+ struct idmap_domain *dom;
+ NTSTATUS ret;
+
+ DEBUG(10, ("Setting mapping %s <-> %s %lu\n",
+ sid_string_static(map->sid),
+ (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
+ (unsigned long)map->xid.id));
+
+ ret = idmap_can_map(map, &dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+
+ DEBUG(10,("set_mapping for domain %s\n", dom->name ));
+
+ return dom->methods->set_mapping(dom, map);
+}
+
+static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
+{
+ struct idmap_domain *dom;
+ struct id_map **unmapped;
+ struct id_map **_ids;
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ int i, u, n;
+
+ if (!ids || !*ids) {
+ DEBUG(1, ("Invalid list of maps\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ctx = talloc_named_const(NULL, 0, "idmap_backends_unixids_to_sids ctx");
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10, ("Query backends to map ids->sids\n"));
+
+ /* start from the default (the last one) and then if there are still
+ * unmapped entries cycle through the others */
+
+ _ids = ids;
+
+ /* make sure all maps are marked as in UNKNOWN status */
+ for (i = 0; _ids[i]; i++) {
+ _ids[i]->status = ID_UNKNOWN;
+ }
+
+ unmapped = NULL;
+ for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */
+
+ dom = idmap_domains[n];
+
+ DEBUG(10, ("Query sids from domain %s\n", dom->name));
+
+ ret = dom->methods->unixids_to_sids(dom, _ids);
+ IDMAP_CHECK_RET(ret);
+
+ unmapped = NULL;
+
+ for (i = 0, u = 0; _ids[i]; i++) {
+ if (_ids[i]->status == ID_UNKNOWN || _ids[i]->status == ID_UNMAPPED) {
+ unmapped = talloc_realloc(ctx, unmapped, struct id_map *, u + 2);
+ IDMAP_CHECK_ALLOC(unmapped);
+ unmapped[u] = _ids[i];
+ u++;
+ }
+ }
+ if (unmapped) {
+ /* terminate the unmapped list */
+ unmapped[u] = NULL;
+ } else { /* no more entries, get out */
+ break;
+ }
+
+ _ids = unmapped;
+
+ }
+
+ if (unmapped) {
+ /* there are still unmapped ids, map them to the unix users/groups domains */
+ for (i = 0; unmapped[i]; i++) {
+ switch (unmapped[i]->xid.type) {
+ case ID_TYPE_UID:
+ uid_to_unix_users_sid((uid_t)unmapped[i]->xid.id, unmapped[i]->sid);
+ unmapped[i]->status = ID_MAPPED;
+ break;
+ case ID_TYPE_GID:
+ gid_to_unix_groups_sid((gid_t)unmapped[i]->xid.id, unmapped[i]->sid);
+ unmapped[i]->status = ID_MAPPED;
+ break;
+ default: /* what?! */
+ unmapped[i]->status = ID_UNKNOWN;
+ break;
+ }
+ }
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
+{
+ struct id_map ***dom_ids;
+ struct idmap_domain *dom;
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ int i, *counters;
+
+ if ( (ctx = talloc_named_const(NULL, 0, "be_sids_to_ids")) == NULL ) {
+ DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10, ("Query backends to map sids->ids\n"));
+
+ /* split list per domain */
+
+ dom_ids = talloc_zero_array(ctx, struct id_map **, num_domains);
+ IDMAP_CHECK_ALLOC(dom_ids);
+ counters = talloc_zero_array(ctx, int, num_domains);
+
+ /* partition the requests by domain */
+
+ for (i = 0; ids[i]; i++) {
+ uint32 idx;
+
+ /* make sure they are unknown to start off */
+ ids[i]->status = ID_UNKNOWN;
+
+ if ( (dom = find_idmap_domain_from_sid( ids[i]->sid )) == NULL ) {
+ /* no vailable idmap_domain. Move on */
+ continue;
+ }
+
+ DEBUG(10,("SID %s is being handled by %s\n",
+ sid_string_static(ids[i]->sid),
+ dom ? dom->name : "none" ));
+
+ idx = find_idmap_domain_index( dom );
+ SMB_ASSERT( idx != -1 );
+
+ dom_ids[idx] = talloc_realloc(ctx, dom_ids[idx],
+ struct id_map *, counters[idx] + 2);
+ IDMAP_CHECK_ALLOC(dom_ids[idx]);
+
+ dom_ids[idx][counters[idx]] = ids[i];
+ counters[idx]++;
+ dom_ids[idx][counters[idx]] = NULL;
+ }
+
+ /* All the ids have been dispatched in the right queues.
+ Let's cycle through the filled ones */
+
+ for (i = 0; i < num_domains; i++) {
+ if (dom_ids[i]) {
+ dom = idmap_domains[i];
+ DEBUG(10, ("Query ids from domain %s\n", dom->name));
+ ret = dom->methods->sids_to_unixids(dom, dom_ids[i]);
+ IDMAP_CHECK_RET(ret);
+ }
+ }
+
+ /* ok all the backends have been contacted at this point */
+ /* let's see if we have any unmapped SID left and act accordingly */
+
+ for (i = 0; ids[i]; i++) {
+ if (ids[i]->status == ID_UNKNOWN || ids[i]->status == ID_UNMAPPED) {
+ /* ok this is an unmapped one, see if we can map it */
+ ret = idmap_new_mapping(ctx, ids[i]);
+ if (NT_STATUS_IS_OK(ret)) {
+ /* successfully mapped */
+ ids[i]->status = ID_MAPPED;
+ } else if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+ /* could not map it */
+ ids[i]->status = ID_UNMAPPED;
+ } else {
+ /* Something very bad happened down there */
+ ids[i]->status = ID_UNKNOWN;
+ }
+ }
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/**************************************************************************
+ idmap interface functions
+**************************************************************************/
+
+NTSTATUS idmap_unixids_to_sids(struct id_map **ids)
+{
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ struct id_map **bids;
+ int i, bi;
+ int bn = 0;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ if (!ids || !*ids) {
+ DEBUG(1, ("Invalid list of maps\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ctx = talloc_named_const(NULL, 0, "idmap_unixids_to_sids ctx");
+ if ( ! ctx) {
+ DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* no ids to be asked to the backends by default */
+ bids = NULL;
+ bi = 0;
+
+ for (i = 0; ids[i]; i++) {
+
+ if ( ! ids[i]->sid) {
+ DEBUG(1, ("invalid null SID in id_map array"));
+ talloc_free(ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ret = idmap_cache_map_id(idmap_cache, ids[i]);
+
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ if ( ! bids) {
+ /* alloc space for ids to be resolved by backends (realloc ten by ten) */
+ bids = talloc_array(ctx, struct id_map *, 10);
+ if ( ! bids) {
+ DEBUG(1, ("Out of memory!\n"));
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ bn = 10;
+ }
+
+ /* add this id to the ones to be retrieved from the backends */
+ bids[bi] = ids[i];
+ bi++;
+
+ /* check if we need to allocate new space on the rids array */
+ if (bi == bn) {
+ bn += 10;
+ bids = talloc_realloc(ctx, bids, struct id_map *, bn);
+ if ( ! bids) {
+ DEBUG(1, ("Out of memory!\n"));
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ /* make sure the last element is NULL */
+ bids[bi] = NULL;
+ }
+ }
+
+ /* let's see if there is any id mapping to be retieved from the backends */
+ if (bi) {
+ ret = idmap_backends_unixids_to_sids(bids);
+ IDMAP_CHECK_RET(ret);
+
+ /* update the cache */
+ for (i = 0; i < bi; i++) {
+ if (bids[i]->status == ID_MAPPED) {
+ ret = idmap_cache_set(idmap_cache, bids[i]);
+ } else if (bids[i]->status == ID_UNKNOWN) {
+ /* return an expired entry in the cache or an unknown */
+ /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * for disconnected mode */
+ idmap_cache_map_id(idmap_cache, ids[i]);
+ } else { /* unmapped */
+ ret = idmap_cache_set_negative_id(idmap_cache, bids[i]);
+ }
+ IDMAP_CHECK_RET(ret);
+ }
+ }
+
+ ret = NT_STATUS_OK;
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+NTSTATUS idmap_sids_to_unixids(struct id_map **ids)
+{
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ struct id_map **bids;
+ int i, bi;
+ int bn = 0;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ if (!ids || !*ids) {
+ DEBUG(1, ("Invalid list of maps\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ctx = talloc_named_const(NULL, 0, "idmap_sids_to_unixids ctx");
+ if ( ! ctx) {
+ DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* no ids to be asked to the backends by default */
+ bids = NULL;
+ bi = 0;
+
+ for (i = 0; ids[i]; i++) {
+
+ if ( ! ids[i]->sid) {
+ DEBUG(1, ("invalid null SID in id_map array\n"));
+ talloc_free(ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ret = idmap_cache_map_sid(idmap_cache, ids[i]);
+
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ if ( ! bids) {
+ /* alloc space for ids to be resolved by backends (realloc ten by ten) */
+ bids = talloc_array(ctx, struct id_map *, 10);
+ if ( ! bids) {
+ DEBUG(1, ("Out of memory!\n"));
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ bn = 10;
+ }
+
+ /* add this id to the ones to be retrieved from the backends */
+ bids[bi] = ids[i];
+ bi++;
+
+ /* check if we need to allocate new space on the ids array */
+ if (bi == bn) {
+ bn += 10;
+ bids = talloc_realloc(ctx, bids, struct id_map *, bn);
+ if ( ! bids) {
+ DEBUG(1, ("Out of memory!\n"));
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ /* make sure the last element is NULL */
+ bids[bi] = NULL;
+ }
+ }
+
+ /* let's see if there is any id mapping to be retieved from the backends */
+ if (bids) {
+ ret = idmap_backends_sids_to_unixids(bids);
+ IDMAP_CHECK_RET(ret);
+
+ /* update the cache */
+ for (i = 0; bids[i]; i++) {
+ if (bids[i]->status == ID_MAPPED) {
+ ret = idmap_cache_set(idmap_cache, bids[i]);
+ } else if (bids[i]->status == ID_UNKNOWN) {
+ /* return an expired entry in the cache or an unknown */
+ /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * for disconnected mode */
+ idmap_cache_map_id(idmap_cache, ids[i]);
+ } else {
+ ret = idmap_cache_set_negative_sid(idmap_cache, bids[i]);
+ }
+ IDMAP_CHECK_RET(ret);
+ }
+ }
+
+ ret = NT_STATUS_OK;
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+NTSTATUS idmap_set_mapping(const struct id_map *id)
+{
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ /* sanity checks */
+ if ((id->sid == NULL) || (id->status != ID_MAPPED)) {
+ DEBUG(1, ("NULL SID or unmapped entry\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* TODO: check uid/gid range ? */
+
+ ctx = talloc_named_const(NULL, 0, "idmap_set_mapping ctx");
+ if ( ! ctx) {
+ DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* set the new mapping */
+ ret = idmap_backends_set_mapping(id);
+ IDMAP_CHECK_RET(ret);
+
+ /* set the mapping in the cache */
+ ret = idmap_cache_set(idmap_cache, id);
+ IDMAP_CHECK_RET(ret);
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/**************************************************************************
+ Dump backend status.
+**************************************************************************/
+
+void idmap_dump_maps(char *logfile)
+{
+ NTSTATUS ret;
+ struct unixid allid;
+ struct id_map *maps;
+ int num_maps;
+ FILE *dump;
+ int i;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return;
+ }
+
+ dump = fopen(logfile, "w");
+ if ( ! dump) {
+ DEBUG(0, ("Unable to open open stream for file [%s], errno: %d\n", logfile, errno));
+ return;
+ }
+
+ allid.type = ID_TYPE_UID;
+ allid.id = 0;
+ alloc_methods->get_id_hwm(&allid);
+ fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id);
+
+ allid.type = ID_TYPE_GID;
+ allid.id = 0;
+ alloc_methods->get_id_hwm(&allid);
+ fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id);
+
+ maps = talloc(idmap_ctx, struct id_map);
+ num_maps = 0;
+
+ for (i = 0; i < num_domains; i++) {
+ if (idmap_domains[i]->methods->dump_data) {
+ idmap_domains[i]->methods->dump_data(idmap_domains[i], &maps, &num_maps);
+ }
+ }
+
+ for (i = 0; i < num_maps; i++) {
+ switch (maps[i].xid.type) {
+ case ID_TYPE_UID:
+ fprintf(dump, "UID %lu %s\n",
+ (unsigned long)maps[i].xid.id,
+ sid_string_static(maps[i].sid));
+ break;
+ case ID_TYPE_GID:
+ fprintf(dump, "GID %lu %s\n",
+ (unsigned long)maps[i].xid.id,
+ sid_string_static(maps[i].sid));
+ break;
+ }
+ }
+
+ fflush(dump);
+ fclose(dump);
+}
+
+char *idmap_fetch_secret(const char *backend, bool alloc,
+ const char *domain, const char *identity)
+{
+ char *tmp, *ret;
+ int r;
+
+ if (alloc) {
+ r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
+ } else {
+ r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
+ }
+
+ if (r < 0)
+ return NULL;
+
+ strupper_m(tmp); /* make sure the key is case insensitive */
+ ret = secrets_fetch_generic(tmp, identity);
+
+ SAFE_FREE( tmp );
+
+ return ret;
+}
diff --git a/source/nsswitch/idmap_ad.c b/source/nsswitch/idmap_ad.c
new file mode 100644
index 00000000000..fee53a0539e
--- /dev/null
+++ b/source/nsswitch/idmap_ad.c
@@ -0,0 +1,816 @@
+/*
+ * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts
+ *
+ * Unix SMB/CIFS implementation.
+ *
+ * Winbind ADS backend functions
+ *
+ * Copyright (C) Andrew Tridgell 2001
+ * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
+ * Copyright (C) Gerald (Jerry) Carter 2004-2007
+ * Copyright (C) Luke Howard 2001-2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
+
+#define IDMAP_AD_MAX_IDS 30
+#define CHECK_ALLOC_DONE(mem) do { \
+ if (!mem) { \
+ DEBUG(0, ("Out of memory!\n")); \
+ ret = NT_STATUS_NO_MEMORY; \
+ goto done; \
+ } \
+} while (0)
+
+struct idmap_ad_context {
+ uint32_t filter_low_id;
+ uint32_t filter_high_id;
+};
+
+NTSTATUS init_module(void);
+
+static ADS_STRUCT *ad_idmap_ads = NULL;
+static struct posix_schema *ad_schema = NULL;
+static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN;
+
+/************************************************************************
+ ***********************************************************************/
+
+static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ BOOL local = False;
+ fstring dc_name;
+ struct in_addr dc_ip;
+
+ if (ad_idmap_ads != NULL) {
+
+ time_t expire;
+ time_t now = time(NULL);
+
+ ads = ad_idmap_ads;
+
+ expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
+
+ /* check for a valid structure */
+ DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
+ (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
+
+ if ( ads->config.realm && (expire > time(NULL))) {
+ return ads;
+ } else {
+ /* we own this ADS_STRUCT so make sure it goes away */
+ DEBUG(7,("Deleting expired krb5 credential cache\n"));
+ ads->is_mine = True;
+ ads_destroy( &ads );
+ ads_kdestroy(WINBIND_CCACHE_NAME);
+ ad_idmap_ads = NULL;
+ TALLOC_FREE( ad_schema );
+ }
+ }
+
+ if (!local) {
+ /* we don't want this to affect the users ccache */
+ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
+ }
+
+ if ( (ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL ) {
+ DEBUG(1,("ads_init failed\n"));
+ return NULL;
+ }
+
+ /* the machine acct password might have change - fetch it every time */
+ SAFE_FREE(ads->auth.password);
+ ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = SMB_STRDUP(lp_realm());
+
+ /* setup server affinity */
+
+ get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip );
+
+ status = ads_connect(ads);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
+ ads_destroy(&ads);
+ return NULL;
+ }
+
+ ads->is_mine = False;
+
+ ad_idmap_ads = ads;
+
+ return ads;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static ADS_STRUCT *ad_idmap_cached_connection(void)
+{
+ ADS_STRUCT *ads = ad_idmap_cached_connection_internal();
+
+ if ( !ads )
+ return NULL;
+
+ /* if we have a valid ADS_STRUCT and the schema model is
+ defined, then we can return here. */
+
+ if ( ad_schema )
+ return ads;
+
+ /* Otherwise, set the schema model */
+
+ if ( (ad_map_type == WB_POSIX_MAP_SFU) ||
+ (ad_map_type == WB_POSIX_MAP_RFC2307) )
+ {
+ ADS_STATUS schema_status;
+
+ schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema);
+ if ( !ADS_ERR_OK(schema_status) ) {
+ DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
+ return NULL;
+ }
+ }
+
+ return ads;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
+{
+ struct idmap_ad_context *ctx;
+ char *config_option;
+ const char *range;
+ ADS_STRUCT *ads;
+
+ /* verify AD is reachable (not critical, we may just be offline at start) */
+ if ( (ads = ad_idmap_cached_connection()) == NULL ) {
+ DEBUG(1, ("WARNING: Could not init an AD connection! Mapping might not work.\n"));
+ }
+
+ if ( (ctx = talloc_zero(dom, struct idmap_ad_context)) == NULL ) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) {
+ DEBUG(0, ("Out of memory!\n"));
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* load ranges */
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if (range && range[0]) {
+ if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
+ (ctx->filter_low_id > ctx->filter_high_id)) {
+ DEBUG(1, ("ERROR: invalid filter range [%s]", range));
+ ctx->filter_low_id = 0;
+ ctx->filter_high_id = 0;
+ }
+ }
+
+ /* idmap AD can work well only if it is the default module (trusts)
+ * with additional BUILTIN and alloc using TDB */
+ if ( ! dom->default_domain) {
+ DEBUG(1, ("WARNING: idmap_ad is not configured as the default domain.\n"
+ "For best results we suggest you to configure this module as\n"
+ "default and configure BULTIN to use idmap_tdb\n"
+ "ex: idmap domains = BUILTIN %s\n"
+ " idmap alloc config: range = 5000 - 9999\n"
+ " idmap config %s: default = yes\n"
+ " idmap config %s: backend = ad\n"
+ " idmap config %s: range = 10000 - 10000000 #this is optional\n"
+ "NOTE: make sure the ranges do not overlap\n",
+ dom->name, dom->name, dom->name, dom->name));
+ }
+
+ if ( !dom->readonly ) {
+ DEBUG(1, ("WARNING: forcing to readonly, as idmap_ad can't write on AD.\n"));
+ dom->readonly = true;
+ }
+
+ dom->private_data = ctx;
+
+ talloc_free(config_option);
+
+ return NT_STATUS_OK;
+}
+
+/************************************************************************
+ Search up to IDMAP_AD_MAX_IDS entries in maps for a match.
+ ***********************************************************************/
+
+static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
+{
+ int i;
+
+ for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
+ if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
+ return maps[i];
+ }
+ }
+
+ return NULL;
+}
+
+/************************************************************************
+ Search up to IDMAP_AD_MAX_IDS entries in maps for a match
+ ***********************************************************************/
+
+static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
+{
+ int i;
+
+ for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
+ if (sid_equal(maps[i]->sid, sid)) {
+ return maps[i];
+ }
+ }
+
+ return NULL;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *memctx;
+ struct idmap_ad_context *ctx;
+ ADS_STATUS rc;
+ ADS_STRUCT *ads;
+ const char *attrs[] = { "sAMAccountType",
+ "objectSid",
+ NULL, /* uidnumber */
+ NULL, /* gidnumber */
+ NULL };
+ LDAPMessage *res = NULL;
+ char *filter = NULL;
+ int idx = 0;
+ int bidx = 0;
+ int count;
+ int i;
+ char *u_filter = NULL;
+ char *g_filter = NULL;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
+
+ if ( (memctx = talloc_new(ctx)) == NULL ) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( (ads = ad_idmap_cached_connection()) == NULL ) {
+ DEBUG(1, ("ADS uninitialized\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ attrs[2] = ad_schema->posix_uidnumber_attr;
+ attrs[3] = ad_schema->posix_gidnumber_attr;
+
+again:
+ bidx = idx;
+ for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
+ switch (ids[idx]->xid.type) {
+ case ID_TYPE_UID:
+ if ( ! u_filter) {
+ u_filter = talloc_asprintf(memctx, "(&(|"
+ "(sAMAccountType=%d)"
+ "(sAMAccountType=%d)"
+ "(sAMAccountType=%d))(|",
+ ATYPE_NORMAL_ACCOUNT,
+ ATYPE_WORKSTATION_TRUST,
+ ATYPE_INTERDOMAIN_TRUST);
+ }
+ u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)",
+ ad_schema->posix_uidnumber_attr,
+ (unsigned long)ids[idx]->xid.id);
+ CHECK_ALLOC_DONE(u_filter);
+ break;
+
+ case ID_TYPE_GID:
+ if ( ! g_filter) {
+ g_filter = talloc_asprintf(memctx, "(&(|"
+ "(sAMAccountType=%d)"
+ "(sAMAccountType=%d))(|",
+ ATYPE_SECURITY_GLOBAL_GROUP,
+ ATYPE_SECURITY_LOCAL_GROUP);
+ }
+ g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)",
+ ad_schema->posix_gidnumber_attr,
+ (unsigned long)ids[idx]->xid.id);
+ CHECK_ALLOC_DONE(g_filter);
+ break;
+
+ default:
+ DEBUG(3, ("Unknown ID type\n"));
+ ids[idx]->status = ID_UNKNOWN;
+ continue;
+ }
+ }
+ filter = talloc_asprintf(memctx, "(|");
+ CHECK_ALLOC_DONE(filter);
+ if ( u_filter) {
+ filter = talloc_asprintf_append(filter, "%s))", u_filter);
+ CHECK_ALLOC_DONE(filter);
+ TALLOC_FREE(u_filter);
+ }
+ if ( g_filter) {
+ filter = talloc_asprintf_append(filter, "%s))", g_filter);
+ CHECK_ALLOC_DONE(filter);
+ TALLOC_FREE(g_filter);
+ }
+ filter = talloc_asprintf_append(filter, ")");
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]\n", filter));
+ rc = ads_search_retry(ads, &res, filter, attrs);
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if ( (count = ads_count_replies(ads, res)) == 0 ) {
+ DEBUG(10, ("No IDs found\n"));
+ }
+
+ for (i = 0; i < count; i++) {
+ LDAPMessage *entry = NULL;
+ DOM_SID sid;
+ enum id_type type;
+ struct id_map *map;
+ uint32_t id;
+ uint32_t atype;
+
+ if (i == 0) { /* first entry */
+ entry = ads_first_entry(ads, res);
+ } else { /* following ones */
+ entry = ads_next_entry(ads, entry);
+ }
+ if ( ! entry) {
+ DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
+ continue;
+ }
+
+ /* first check if the SID is present */
+ if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
+ DEBUG(2, ("Could not retrieve SID from entry\n"));
+ continue;
+ }
+
+ /* get type */
+ if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
+ DEBUG(1, ("could not get SAM account type\n"));
+ continue;
+ }
+
+ switch (atype & 0xF0000000) {
+ case ATYPE_SECURITY_GLOBAL_GROUP:
+ case ATYPE_SECURITY_LOCAL_GROUP:
+ type = ID_TYPE_GID;
+ break;
+ case ATYPE_NORMAL_ACCOUNT:
+ case ATYPE_WORKSTATION_TRUST:
+ case ATYPE_INTERDOMAIN_TRUST:
+ type = ID_TYPE_UID;
+ break;
+ default:
+ DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
+ continue;
+ }
+
+ if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
+ ad_schema->posix_uidnumber_attr :
+ ad_schema->posix_gidnumber_attr,
+ &id))
+ {
+ DEBUG(1, ("Could not get unix ID\n"));
+ continue;
+ }
+
+ if ((id == 0) ||
+ (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ id, ctx->filter_low_id, ctx->filter_high_id));
+ continue;
+ }
+
+ map = find_map_by_id(&ids[bidx], type, id);
+ if (!map) {
+ DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
+ continue;
+ }
+
+ sid_copy(map->sid, &sid);
+
+ /* mapped */
+ map->status = ID_MAPPED;
+
+ DEBUG(10, ("Mapped %s -> %lu (%d)\n",
+ sid_string_static(map->sid),
+ (unsigned long)map->xid.id,
+ map->xid.type));
+ }
+
+ if (res) {
+ ads_msgfree(ads, res);
+ }
+
+ if (ids[idx]) { /* still some values to map */
+ goto again;
+ }
+
+ ret = NT_STATUS_OK;
+
+ /* mark all unknown ones as unmapped */
+ for (i = 0; ids[i]; i++) {
+ if (ids[i]->status == ID_UNKNOWN)
+ ids[i]->status = ID_UNMAPPED;
+ }
+
+done:
+ talloc_free(memctx);
+ return ret;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *memctx;
+ struct idmap_ad_context *ctx;
+ ADS_STATUS rc;
+ ADS_STRUCT *ads;
+ const char *attrs[] = { "sAMAccountType",
+ "objectSid",
+ NULL, /* attr_uidnumber */
+ NULL, /* attr_gidnumber */
+ NULL };
+ LDAPMessage *res = NULL;
+ char *filter = NULL;
+ int idx = 0;
+ int bidx = 0;
+ int count;
+ int i;
+ char *sidstr;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
+
+ if ( (memctx = talloc_new(ctx)) == NULL ) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( (ads = ad_idmap_cached_connection()) == NULL ) {
+ DEBUG(1, ("ADS uninitialized\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ attrs[2] = ad_schema->posix_uidnumber_attr;
+ attrs[3] = ad_schema->posix_gidnumber_attr;
+
+again:
+ filter = talloc_asprintf(memctx, "(&(|"
+ "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
+ "(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
+ ")(|",
+ ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
+ ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
+
+ CHECK_ALLOC_DONE(filter);
+
+ bidx = idx;
+ for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
+
+ sidstr = sid_binstring(ids[idx]->sid);
+ filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr);
+
+ free(sidstr);
+ CHECK_ALLOC_DONE(filter);
+ }
+ filter = talloc_asprintf_append(filter, "))");
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]\n", filter));
+
+ rc = ads_search_retry(ads, &res, filter, attrs);
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if ( (count = ads_count_replies(ads, res)) == 0 ) {
+ DEBUG(10, ("No IDs found\n"));
+ }
+
+ for (i = 0; i < count; i++) {
+ LDAPMessage *entry = NULL;
+ DOM_SID sid;
+ enum id_type type;
+ struct id_map *map;
+ uint32_t id;
+ uint32_t atype;
+
+ if (i == 0) { /* first entry */
+ entry = ads_first_entry(ads, res);
+ } else { /* following ones */
+ entry = ads_next_entry(ads, entry);
+ }
+ if ( ! entry) {
+ DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
+ continue;
+ }
+
+ /* first check if the SID is present */
+ if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
+ DEBUG(2, ("Could not retrieve SID from entry\n"));
+ continue;
+ }
+
+ map = find_map_by_sid(&ids[bidx], &sid);
+ if (!map) {
+ DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
+ continue;
+ }
+
+ /* get type */
+ if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
+ DEBUG(1, ("could not get SAM account type\n"));
+ continue;
+ }
+
+ switch (atype & 0xF0000000) {
+ case ATYPE_SECURITY_GLOBAL_GROUP:
+ case ATYPE_SECURITY_LOCAL_GROUP:
+ type = ID_TYPE_GID;
+ break;
+ case ATYPE_NORMAL_ACCOUNT:
+ case ATYPE_WORKSTATION_TRUST:
+ case ATYPE_INTERDOMAIN_TRUST:
+ type = ID_TYPE_UID;
+ break;
+ default:
+ DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
+ continue;
+ }
+
+ if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
+ ad_schema->posix_uidnumber_attr :
+ ad_schema->posix_gidnumber_attr,
+ &id))
+ {
+ DEBUG(1, ("Could not get unix ID\n"));
+ continue;
+ }
+ if ((id == 0) ||
+ (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ id, ctx->filter_low_id, ctx->filter_high_id));
+ continue;
+ }
+
+ /* mapped */
+ map->xid.type = type;
+ map->xid.id = id;
+ map->status = ID_MAPPED;
+
+ DEBUG(10, ("Mapped %s -> %lu (%d)\n",
+ sid_string_static(map->sid),
+ (unsigned long)map->xid.id,
+ map->xid.type));
+ }
+
+ if (res) {
+ ads_msgfree(ads, res);
+ }
+
+ if (ids[idx]) { /* still some values to map */
+ goto again;
+ }
+
+ ret = NT_STATUS_OK;
+
+ /* mark all unknwon ones as unmapped */
+ for (i = 0; ids[i]; i++) {
+ if (ids[i]->status == ID_UNKNOWN)
+ ids[i]->status = ID_UNMAPPED;
+ }
+
+done:
+ talloc_free(memctx);
+ return ret;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
+{
+ ADS_STRUCT *ads = ad_idmap_ads;
+
+ if (ads != NULL) {
+ /* we own this ADS_STRUCT so make sure it goes away */
+ ads->is_mine = True;
+ ads_destroy( &ads );
+ ad_idmap_ads = NULL;
+ }
+
+ TALLOC_FREE( ad_schema );
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * nss_info_{sfu,rfc2307}
+ */
+
+/************************************************************************
+ Initialize the {sfu,rfc2307} state
+ ***********************************************************************/
+
+static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
+{
+ /* Sanity check if we have previously been called with a
+ different schema model */
+
+ if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
+ (ad_map_type != WB_POSIX_MAP_SFU) )
+ {
+ DEBUG(0,("nss_sfu_init: Posix Map type has already been set. "
+ "Mixed schema models not supported!\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ ad_map_type = WB_POSIX_MAP_SFU;
+
+ if ( !ad_idmap_ads )
+ return idmap_ad_initialize( NULL, NULL );
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
+{
+ /* Sanity check if we have previously been called with a
+ different schema model */
+
+ if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
+ (ad_map_type != WB_POSIX_MAP_RFC2307) )
+ {
+ DEBUG(0,("nss_rfc2307_init: Posix Map type has already been set. "
+ "Mixed schema models not supported!\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ ad_map_type = WB_POSIX_MAP_RFC2307;
+
+ if ( !ad_idmap_ads )
+ return idmap_ad_initialize( NULL, NULL );
+
+ return NT_STATUS_OK;
+}
+
+
+/************************************************************************
+ ***********************************************************************/
+static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
+ const DOM_SID *sid,
+ TALLOC_CTX *ctx,
+ ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ char **homedir,
+ char **shell,
+ char **gecos,
+ uint32 *gid )
+{
+ ADS_STRUCT *ads_internal = NULL;
+
+ /* We are assuming that the internal ADS_STRUCT is for the
+ same forest as the incoming *ads pointer */
+
+ ads_internal = ad_idmap_cached_connection();
+
+ if ( !ads_internal || !ad_schema )
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ if ( !homedir || !shell || !gecos )
+ return NT_STATUS_INVALID_PARAMETER;
+
+ *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr );
+ *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr );
+ *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr );
+
+ if ( gid ) {
+ if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
+ *gid = 0;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS nss_ad_close( void )
+{
+ /* nothing to do. All memory is free()'d by the idmap close_fn() */
+
+ return NT_STATUS_OK;
+}
+
+/************************************************************************
+ Function dispatch tables for the idmap and nss plugins
+ ***********************************************************************/
+
+static struct idmap_methods ad_methods = {
+ .init = idmap_ad_initialize,
+ .unixids_to_sids = idmap_ad_unixids_to_sids,
+ .sids_to_unixids = idmap_ad_sids_to_unixids,
+ .close_fn = idmap_ad_close
+};
+
+/* The SFU and RFC2307 NSS plugins share everything but the init
+ function which sets the intended schema model to use */
+
+static struct nss_info_methods nss_rfc2307_methods = {
+ .init = nss_rfc2307_init,
+ .get_nss_info = nss_ad_get_info,
+ .close_fn = nss_ad_close
+};
+
+static struct nss_info_methods nss_sfu_methods = {
+ .init = nss_sfu_init,
+ .get_nss_info = nss_ad_get_info,
+ .close_fn = nss_ad_close
+};
+
+
+/************************************************************************
+ Initialize the plugins
+ ***********************************************************************/
+
+NTSTATUS idmap_ad_init(void)
+{
+ static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
+ static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
+ static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
+
+ /* Always register the AD method first in order to get the
+ idmap_domain interface called */
+
+ if ( !NT_STATUS_IS_OK(status_idmap_ad) ) {
+ status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
+ "ad", &ad_methods);
+ if ( !NT_STATUS_IS_OK(status_idmap_ad) )
+ return status_idmap_ad;
+ }
+
+ if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
+ status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
+ "rfc2307", &nss_rfc2307_methods );
+ if ( !NT_STATUS_IS_OK(status_nss_rfc2307) )
+ return status_nss_rfc2307;
+ }
+
+ if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) {
+ status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
+ "sfu", &nss_sfu_methods );
+ if ( !NT_STATUS_IS_OK(status_nss_sfu) )
+ return status_nss_sfu;
+ }
+
+ return NT_STATUS_OK;
+}
+
diff --git a/source/nsswitch/idmap_cache.c b/source/nsswitch/idmap_cache.c
new file mode 100644
index 00000000000..897dd9c4f5b
--- /dev/null
+++ b/source/nsswitch/idmap_cache.c
@@ -0,0 +1,530 @@
+/*
+ Unix SMB/CIFS implementation.
+ ID Mapping Cache
+
+ based on gencache
+
+ Copyright (C) Simo Sorce 2006
+ Copyright (C) Rafal Szczesniak 2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
+
+#include "includes.h"
+
+#define TIMEOUT_LEN 12
+#define IDMAP_CACHE_DATA_FMT "%12u/%s"
+#define IDMAP_READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us"
+
+struct idmap_cache_ctx {
+ TDB_CONTEXT *tdb;
+};
+
+static int idmap_cache_destructor(struct idmap_cache_ctx *cache)
+{
+ int ret = 0;
+
+ if (cache && cache->tdb) {
+ ret = tdb_close(cache->tdb);
+ cache->tdb = NULL;
+ }
+
+ return ret;
+}
+
+struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx)
+{
+ struct idmap_cache_ctx *cache;
+ char* cache_fname = NULL;
+
+ cache = talloc(memctx, struct idmap_cache_ctx);
+ if ( ! cache) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NULL;
+ }
+
+ cache_fname = lock_path("idmap_cache.tdb");
+
+ DEBUG(10, ("Opening cache file at %s\n", cache_fname));
+
+ cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+
+ if (!cache->tdb) {
+ DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname));
+ return NULL;
+ }
+
+ talloc_set_destructor(cache, idmap_cache_destructor);
+
+ return cache;
+}
+
+void idmap_cache_shutdown(struct idmap_cache_ctx *cache)
+{
+ talloc_free(cache);
+}
+
+NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct id_map *id)
+{
+ *sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", sid_string_static(id->sid));
+ if ( ! *sidkey) {
+ DEBUG(1, ("failed to build sidkey, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS idmap_cache_build_idkey(TALLOC_CTX *ctx, char **idkey, const struct id_map *id)
+{
+ *idkey = talloc_asprintf(ctx, "IDMAP/%s/%lu",
+ (id->xid.type==ID_TYPE_UID)?"UID":"GID",
+ (unsigned long)id->xid.id);
+ if ( ! *idkey) {
+ DEBUG(1, ("failed to build idkey, OOM?\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id)
+{
+ NTSTATUS ret;
+ time_t timeout = time(NULL) + lp_idmap_expire_time();
+ TDB_DATA keybuf, databuf;
+ char *sidkey;
+ char *idkey;
+ char *valstr;
+
+ ret = idmap_cache_build_sidkey(cache, &sidkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ /* use sidkey as the local memory ctx */
+ ret = idmap_cache_build_idkey(sidkey, &idkey, id);
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ /* save SID -> ID */
+
+ /* use sidkey as the local memory ctx */
+ valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey);
+ if (!valstr) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ keybuf.dptr = sidkey;
+ keybuf.dsize = strlen(sidkey)+1;
+ databuf.dptr = valstr;
+ databuf.dsize = strlen(valstr)+1;
+ DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
+ " %s (%d seconds %s)\n", keybuf.dptr, valstr , ctime(&timeout),
+ (int)(timeout - time(NULL)),
+ timeout > time(NULL) ? "ahead" : "in the past"));
+
+ if (tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE) != 0) {
+ DEBUG(3, ("Failed to store cache entry!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* save ID -> SID */
+
+ /* use sidkey as the local memory ctx */
+ valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey);
+ if (!valstr) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ keybuf.dptr = idkey;
+ keybuf.dsize = strlen(idkey)+1;
+ databuf.dptr = valstr;
+ databuf.dsize = strlen(valstr)+1;
+ DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
+ " %s (%d seconds %s)\n", keybuf.dptr, valstr, ctime(&timeout),
+ (int)(timeout - time(NULL)),
+ timeout > time(NULL) ? "ahead" : "in the past"));
+
+ if (tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE) != 0) {
+ DEBUG(3, ("Failed to store cache entry!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(sidkey);
+ return ret;
+}
+
+NTSTATUS idmap_cache_del(struct idmap_cache_ctx *cache, const struct id_map *id)
+{
+ NTSTATUS ret;
+ TDB_DATA keybuf;
+ char *sidkey = NULL;
+ char *idkey = NULL;
+
+ ret = idmap_cache_build_sidkey(cache, &sidkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ ret = idmap_cache_build_idkey(cache, &idkey, id);
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ /* delete SID */
+
+ keybuf.dptr = sidkey;
+ keybuf.dsize = strlen(sidkey)+1;
+ DEBUG(10, ("Deleting cache entry (key = %s)\n", keybuf.dptr));
+
+ if (tdb_delete(cache->tdb, keybuf) != 0) {
+ DEBUG(3, ("Failed to delete cache entry!\n"));
+ }
+
+ /* delete ID */
+
+ keybuf.dptr = idkey;
+ keybuf.dsize = strlen(idkey)+1;
+ DEBUG(10, ("Deleting cache entry (key = %s)\n", keybuf.dptr));
+
+ if (tdb_delete(cache->tdb, keybuf) != 0) {
+ DEBUG(3, ("Failed to delete cache entry!\n"));
+ }
+
+done:
+ talloc_free(sidkey);
+ talloc_free(idkey);
+ return ret;
+}
+
+NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id)
+{
+ NTSTATUS ret;
+ time_t timeout = time(NULL) + lp_idmap_negative_time();
+ TDB_DATA keybuf, databuf;
+ char *sidkey;
+ char *valstr;
+
+ ret = idmap_cache_build_sidkey(cache, &sidkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ /* use sidkey as the local memory ctx */
+ valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE");
+ if (!valstr) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ keybuf.dptr = sidkey;
+ keybuf.dsize = strlen(sidkey)+1;
+ databuf.dptr = valstr;
+ databuf.dsize = strlen(valstr)+1;
+ DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
+ " %s (%d seconds %s)\n", keybuf.dptr, valstr, ctime(&timeout),
+ (int)(timeout - time(NULL)),
+ timeout > time(NULL) ? "ahead" : "in the past"));
+
+ if (tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE) != 0) {
+ DEBUG(3, ("Failed to store cache entry!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+done:
+ talloc_free(sidkey);
+ return ret;
+}
+
+NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id)
+{
+ NTSTATUS ret;
+ time_t timeout = time(NULL) + lp_idmap_negative_time();
+ TDB_DATA keybuf, databuf;
+ char *idkey;
+ char *valstr;
+
+ ret = idmap_cache_build_idkey(cache, &idkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ /* use idkey as the local memory ctx */
+ valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE");
+ if (!valstr) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ keybuf.dptr = idkey;
+ keybuf.dsize = strlen(idkey)+1;
+ databuf.dptr = valstr;
+ databuf.dsize = strlen(valstr)+1;
+ DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
+ " %s (%d seconds %s)\n", keybuf.dptr, valstr, ctime(&timeout),
+ (int)(timeout - time(NULL)),
+ timeout > time(NULL) ? "ahead" : "in the past"));
+
+ if (tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE) != 0) {
+ DEBUG(3, ("Failed to store cache entry!\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+done:
+ talloc_free(idkey);
+ return ret;
+}
+
+NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value)
+{
+ char *rem;
+
+ /* see if it is a sid */
+ if ( ! strncmp("IDMAP/SID/", value, 10)) {
+
+ if ( ! string_to_sid(id->sid, &value[10])) {
+ goto failed;
+ }
+
+ id->status = ID_MAPPED;
+
+ return NT_STATUS_OK;
+ }
+
+ /* not a SID see if it is an UID or a GID */
+ if ( ! strncmp("IDMAP/UID/", value, 10)) {
+
+ /* a uid */
+ id->xid.type = ID_TYPE_UID;
+
+ } else if ( ! strncmp("IDMAP/GID/", value, 10)) {
+
+ /* a gid */
+ id->xid.type = ID_TYPE_GID;
+
+ } else {
+
+ /* a completely bogus value bail out */
+ goto failed;
+ }
+
+ id->xid.id = strtol(&value[10], &rem, 0);
+ if (*rem != '\0') {
+ goto failed;
+ }
+
+ id->status = ID_MAPPED;
+
+ return NT_STATUS_OK;
+
+failed:
+ DEBUG(1, ("invalid value: %s\n", value));
+ id->status = ID_UNKNOWN;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+}
+
+BOOL idmap_cache_is_negative(const char *val)
+{
+ if ( ! strcmp("IDMAP/NEGATIVE", val)) {
+ return True;
+ }
+ return False;
+}
+
+/* search the cahce for the SID an return a mapping if found *
+ *
+ * 3 cases are possible
+ *
+ * 1 map found
+ * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned
+ * 2 map not found
+ * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
+ * 3 negative cache found
+ * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
+ *
+ * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
+ * is needed.
+ */
+
+NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
+{
+ NTSTATUS ret;
+ TDB_DATA keybuf, databuf;
+ time_t t;
+ char *sidkey;
+ char *endptr;
+
+ /* make sure it is marked as not mapped by default */
+ id->status = ID_UNKNOWN;
+
+ ret = idmap_cache_build_sidkey(cache, &sidkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ keybuf.dptr = sidkey;
+ keybuf.dsize = strlen(sidkey)+1;
+
+ databuf = tdb_fetch(cache->tdb, keybuf);
+
+ if (databuf.dptr == NULL) {
+ DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ t = strtol(databuf.dptr, &endptr, 10);
+
+ if ((endptr == NULL) || (*endptr != '/')) {
+ DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr));
+ /* remove the entry */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* check it is not negative */
+ if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
+
+ DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
+ "timeout = %s", t > time(NULL) ? "valid" :
+ "expired", sidkey, endptr+1, ctime(&t)));
+
+ /* this call if successful will also mark the entry as mapped */
+ ret = idmap_cache_fill_map(id, endptr+1);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* if not valid form delete the entry */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */
+
+ if (t <= time(NULL)) {
+ /* We're expired, set an error code for upper layer */
+ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ }
+ } else {
+ if (t <= time(NULL)) {
+ /* We're expired, delete the entry and return not mapped */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ } else {
+ /* this is not mapped as it was a negative cache hit */
+ id->status = ID_UNMAPPED;
+ ret = NT_STATUS_OK;
+ }
+ }
+
+done:
+ SAFE_FREE(databuf.dptr);
+ talloc_free(sidkey);
+ return ret;
+}
+
+/* search the cahce for the ID an return a mapping if found *
+ *
+ * 3 cases are possible
+ *
+ * 1 map found
+ * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned
+ * 2 map not found
+ * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
+ * 3 negative cache found
+ * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
+ *
+ * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
+ * is needed.
+ */
+
+NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
+{
+ NTSTATUS ret;
+ TDB_DATA keybuf, databuf;
+ time_t t;
+ char *idkey;
+ char *endptr;
+
+ /* make sure it is marked as not mapped by default */
+ id->status = ID_UNKNOWN;
+
+ ret = idmap_cache_build_idkey(cache, &idkey, id);
+ if (!NT_STATUS_IS_OK(ret)) return ret;
+
+ keybuf.dptr = idkey;
+ keybuf.dsize = strlen(idkey)+1;
+
+ databuf = tdb_fetch(cache->tdb, keybuf);
+
+ if (databuf.dptr == NULL) {
+ DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ t = strtol(databuf.dptr, &endptr, 10);
+
+ if ((endptr == NULL) || (*endptr != '/')) {
+ DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr));
+ /* remove the entry */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* check it is not negative */
+ if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
+
+ DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
+ "timeout = %s", t > time(NULL) ? "valid" :
+ "expired", idkey, endptr+1, ctime(&t)));
+
+ /* this call if successful will also mark the entry as mapped */
+ ret = idmap_cache_fill_map(id, endptr+1);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* if not valid form delete the entry */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* here ret == NT_STATUS_OK and id->mapped = True */
+
+ if (t <= time(NULL)) {
+ /* We're expired, set an error code for upper layer */
+ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
+ }
+ } else {
+ if (t <= time(NULL)) {
+ /* We're expired, delete the entry and return not mapped */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
+ } else {
+ /* this is not mapped is it was a negative cache hit */
+ id->status = ID_UNMAPPED;
+ ret = NT_STATUS_OK;
+ }
+ }
+done:
+ SAFE_FREE(databuf.dptr);
+ talloc_free(idkey);
+ return ret;
+}
+
diff --git a/source/nsswitch/idmap_ldap.c b/source/nsswitch/idmap_ldap.c
new file mode 100644
index 00000000000..8cccbcecf4c
--- /dev/null
+++ b/source/nsswitch/idmap_ldap.c
@@ -0,0 +1,1364 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap LDAP backend
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Gerald Carter 2003
+ Copyright (C) Simo Sorce 2003-2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "smbldap.h"
+
+struct idmap_ldap_context {
+ struct smbldap_state *smbldap_state;
+ char *url;
+ char *suffix;
+ char *user_dn;
+ uint32_t filter_low_id, filter_high_id; /* Filter range */
+ BOOL anon;
+};
+
+struct idmap_ldap_alloc_context {
+ struct smbldap_state *smbldap_state;
+ char *url;
+ char *suffix;
+ char *user_dn;
+ uid_t low_uid, high_uid; /* Range of uids */
+ gid_t low_gid, high_gid; /* Range of gids */
+
+};
+
+#define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
+
+/**********************************************************************
+ IDMAP ALLOC TDB BACKEND
+**********************************************************************/
+
+static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
+
+/*********************************************************************
+ ********************************************************************/
+
+static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
+ struct smbldap_state *ldap_state,
+ const char *config_option,
+ struct idmap_domain *dom,
+ char **dn )
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ char *user_dn = NULL;
+ char *secret = NULL;
+ const char *tmp = NULL;
+
+ /* assume anonymous if we don't have a specified user */
+
+ tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
+
+ if ( tmp ) {
+ secret = idmap_fetch_secret("ldap", false, dom->name, tmp);
+ if (!secret) {
+ DEBUG(0, ("get_credentials: Unable to fetch "
+ "auth credentials for %s in %s\n",
+ tmp, dom->name));
+ ret = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+ *dn = talloc_strdup(mem_ctx, tmp);
+ CHECK_ALLOC_DONE(*dn);
+ } else {
+ if ( !fetch_ldap_pw( &user_dn, &secret ) ) {
+ DEBUG(2, ("get_credentials: Failed to lookup ldap "
+ "bind creds. Using anonymous connection.\n"));
+ *dn = talloc_strdup( mem_ctx, "" );
+ } else {
+ *dn = talloc_strdup(mem_ctx, user_dn);
+ SAFE_FREE( user_dn );
+ CHECK_ALLOC_DONE(*dn);
+ }
+ }
+
+ smbldap_set_creds(ldap_state, false, *dn, secret);
+ ret = NT_STATUS_OK;
+
+ done:
+ SAFE_FREE( secret );
+
+ return ret;
+}
+
+
+/**********************************************************************
+ Verify the sambaUnixIdPool entry in the directory.
+**********************************************************************/
+
+static NTSTATUS verify_idpool(void)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *ctx;
+ LDAPMessage *result = NULL;
+ LDAPMod **mods = NULL;
+ const char **attr_list;
+ char *filter;
+ int count;
+ int rc;
+
+ if ( ! idmap_alloc_ldap) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ctx = talloc_new(idmap_alloc_ldap);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
+ CHECK_ALLOC_DONE(filter);
+
+ attr_list = get_attr_list(ctx, idpool_attr_list);
+ CHECK_ALLOC_DONE(attr_list);
+
+ rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
+ idmap_alloc_ldap->suffix,
+ LDAP_SCOPE_SUBTREE,
+ filter,
+ attr_list,
+ 0,
+ &result);
+
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+
+ ldap_msgfree(result);
+
+ if ( count > 1 ) {
+ DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
+ filter, idmap_alloc_ldap->suffix));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ else if (count == 0) {
+ char *uid_str, *gid_str;
+
+ uid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_uid);
+ gid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_gid);
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectClass", LDAP_OBJ_IDPOOL);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER),
+ uid_str);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER),
+ gid_str);
+ if (mods) {
+ rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
+ idmap_alloc_ldap->suffix,
+ mods);
+ ldap_mods_free(mods, True);
+ } else {
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ }
+
+ ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/*****************************************************************************
+ Initialise idmap database.
+*****************************************************************************/
+
+static NTSTATUS idmap_ldap_alloc_init(const char *params)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ const char *range;
+ const char *tmp;
+ uid_t low_uid = 0;
+ uid_t high_uid = 0;
+ gid_t low_gid = 0;
+ gid_t high_gid = 0;
+
+ idmap_alloc_ldap = talloc_zero(NULL, struct idmap_ldap_alloc_context);
+ CHECK_ALLOC_DONE( idmap_alloc_ldap );
+
+ /* load ranges */
+
+ idmap_alloc_ldap->low_uid = 0;
+ idmap_alloc_ldap->high_uid = 0;
+ idmap_alloc_ldap->low_gid = 0;
+ idmap_alloc_ldap->high_gid = 0;
+
+ range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
+ if (range && range[0]) {
+ unsigned low_id, high_id;
+
+ if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
+ if (low_id < high_id) {
+ idmap_alloc_ldap->low_gid = idmap_alloc_ldap->low_uid = low_id;
+ idmap_alloc_ldap->high_gid = idmap_alloc_ldap->high_uid = high_id;
+ } else {
+ DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
+ }
+ } else {
+ DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
+ }
+ }
+
+ if (lp_idmap_uid(&low_uid, &high_uid)) {
+ idmap_alloc_ldap->low_uid = low_uid;
+ idmap_alloc_ldap->high_uid = high_uid;
+ }
+
+ if (lp_idmap_gid(&low_gid, &high_gid)) {
+ idmap_alloc_ldap->low_gid = low_gid;
+ idmap_alloc_ldap->high_gid= high_gid;
+ }
+
+ if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
+ DEBUG(1, ("idmap uid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
+ DEBUG(1, ("idmap gid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (params && *params) {
+ /* assume location is the only parameter */
+ idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
+ } else {
+ tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_url", NULL);
+
+ if ( ! tmp) {
+ DEBUG(1, ("ERROR: missing idmap ldap url\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
+ }
+ CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
+
+ tmp = lp_ldap_idmap_suffix();
+ if ( ! tmp || ! *tmp) {
+ tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_base_dn", NULL);
+ }
+ if ( ! tmp) {
+ tmp = lp_ldap_suffix();
+ if (tmp) {
+ DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
+ DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
+ }
+ if ( ! tmp) {
+ DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ }
+
+ idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
+ CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
+
+ ret = smbldap_init(idmap_alloc_ldap, idmap_alloc_ldap->url,
+ &idmap_alloc_ldap->smbldap_state);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
+ idmap_alloc_ldap->url));
+ goto done;
+ }
+
+ ret = get_credentials( idmap_alloc_ldap,
+ idmap_alloc_ldap->smbldap_state,
+ "idmap alloc config", NULL,
+ &idmap_alloc_ldap->user_dn );
+ if ( !NT_STATUS_IS_OK(ret) ) {
+ DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
+ "credentials (%s)\n", nt_errstr(ret)));
+ goto done;
+ }
+
+ /* see if the idmap suffix and sub entries exists */
+
+ ret = verify_idpool();
+
+ done:
+ if ( !NT_STATUS_IS_OK( ret ) )
+ TALLOC_FREE( idmap_alloc_ldap );
+
+ return ret;
+}
+
+/********************************
+ Allocate a new uid or gid
+********************************/
+
+static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
+{
+ TALLOC_CTX *ctx;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ int rc = LDAP_SERVER_DOWN;
+ int count = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ char *id_str;
+ char *new_id_str;
+ char *filter = NULL;
+ const char *dn = NULL;
+ const char **attr_list;
+ const char *type;
+
+ if ( ! idmap_alloc_ldap) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ctx = talloc_new(idmap_alloc_ldap);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* get type */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
+ break;
+
+ case ID_TYPE_GID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
+ CHECK_ALLOC_DONE(filter);
+
+ attr_list = get_attr_list(ctx, idpool_attr_list);
+ CHECK_ALLOC_DONE(attr_list);
+
+ DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
+
+ rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
+ idmap_alloc_ldap->suffix,
+ LDAP_SCOPE_SUBTREE, filter,
+ attr_list, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ talloc_autofree_ldapmsg(ctx, result);
+
+ count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+ if (count != 1) {
+ DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+
+ dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
+ if ( ! dn) {
+ goto done;
+ }
+
+ if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
+ entry, type, ctx))) {
+ DEBUG(0,("%s attribute not found\n", type));
+ goto done;
+ }
+ if ( ! id_str) {
+ DEBUG(0,("Out of memory\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ xid->id = strtoul(id_str, NULL, 10);
+
+ /* make sure we still have room to grow */
+
+ switch (xid->type) {
+ case ID_TYPE_UID:
+ if (xid->id > idmap_alloc_ldap->high_uid) {
+ DEBUG(0,("Cannot allocate uid above %lu!\n",
+ (unsigned long)idmap_alloc_ldap->high_uid));
+ goto done;
+ }
+ break;
+
+ case ID_TYPE_GID:
+ if (xid->id > idmap_alloc_ldap->high_gid) {
+ DEBUG(0,("Cannot allocate gid above %lu!\n",
+ (unsigned long)idmap_alloc_ldap->high_uid));
+ goto done;
+ }
+ break;
+
+ default:
+ /* impossible */
+ goto done;
+ }
+
+ new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
+ if ( ! new_id_str) {
+ DEBUG(0,("Out of memory\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
+
+ if (mods == NULL) {
+ DEBUG(0,("smbldap_set_mod() failed.\n"));
+ goto done;
+ }
+
+ DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str, new_id_str));
+
+ rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
+
+ ldap_mods_free(mods, True);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/**********************************
+ Get current highest id.
+**********************************/
+
+static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
+{
+ TALLOC_CTX *memctx;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ int rc = LDAP_SERVER_DOWN;
+ int count = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ char *id_str;
+ char *filter = NULL;
+ const char **attr_list;
+ const char *type;
+
+ if ( ! idmap_alloc_ldap) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ memctx = talloc_new(idmap_alloc_ldap);
+ if ( ! memctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* get type */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
+ break;
+
+ case ID_TYPE_GID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
+ CHECK_ALLOC_DONE(filter);
+
+ attr_list = get_attr_list(memctx, idpool_attr_list);
+ CHECK_ALLOC_DONE(attr_list);
+
+ rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
+ idmap_alloc_ldap->suffix,
+ LDAP_SCOPE_SUBTREE, filter,
+ attr_list, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ talloc_autofree_ldapmsg(memctx, result);
+
+ count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+ if (count != 1) {
+ DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+
+ id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
+ entry, type, memctx);
+ if ( ! id_str) {
+ DEBUG(0,("%s attribute not found\n", type));
+ goto done;
+ }
+ if ( ! id_str) {
+ DEBUG(0,("Out of memory\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ xid->id = strtoul(id_str, NULL, 10);
+
+ ret = NT_STATUS_OK;
+done:
+ talloc_free(memctx);
+ return ret;
+}
+/**********************************
+ Set highest id.
+**********************************/
+
+static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
+{
+ TALLOC_CTX *ctx;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ int rc = LDAP_SERVER_DOWN;
+ int count = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ char *new_id_str;
+ char *filter = NULL;
+ const char *dn = NULL;
+ const char **attr_list;
+ const char *type;
+
+ if ( ! idmap_alloc_ldap) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ctx = talloc_new(idmap_alloc_ldap);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* get type */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
+ break;
+
+ case ID_TYPE_GID:
+ type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
+ CHECK_ALLOC_DONE(filter);
+
+ attr_list = get_attr_list(ctx, idpool_attr_list);
+ CHECK_ALLOC_DONE(attr_list);
+
+ rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
+ idmap_alloc_ldap->suffix,
+ LDAP_SCOPE_SUBTREE, filter,
+ attr_list, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ talloc_autofree_ldapmsg(ctx, result);
+
+ count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+ if (count != 1) {
+ DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
+ goto done;
+ }
+
+ entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
+
+ dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
+ if ( ! dn) {
+ goto done;
+ }
+
+ new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
+ if ( ! new_id_str) {
+ DEBUG(0,("Out of memory\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
+
+ if (mods == NULL) {
+ DEBUG(0,("smbldap_set_mod() failed.\n"));
+ goto done;
+ }
+
+ rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
+
+ ldap_mods_free(mods, True);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/**********************************
+ Close idmap ldap alloc
+**********************************/
+
+static NTSTATUS idmap_ldap_alloc_close(void)
+{
+ if (idmap_alloc_ldap) {
+ smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
+ DEBUG(5,("The connection to the LDAP server was closed\n"));
+ /* maybe free the results here --metze */
+ TALLOC_FREE(idmap_alloc_ldap);
+ }
+ return NT_STATUS_OK;
+}
+
+
+/**********************************************************************
+ IDMAP MAPPING LDAP BACKEND
+**********************************************************************/
+
+static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
+{
+ smbldap_free_struct(&ctx->smbldap_state);
+ DEBUG(5,("The connection to the LDAP server was closed\n"));
+ /* maybe free the results here --metze */
+
+ return 0;
+}
+
+/********************************
+ Initialise idmap database.
+********************************/
+
+static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
+{
+ NTSTATUS ret;
+ struct idmap_ldap_context *ctx = NULL;
+ char *config_option = NULL;
+ const char *range = NULL;
+ const char *tmp = NULL;
+
+ ctx = talloc_zero(dom, struct idmap_ldap_context);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+ if ( ! config_option) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* load ranges */
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if (range && range[0]) {
+ if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
+ (ctx->filter_low_id > ctx->filter_high_id)) {
+ DEBUG(1, ("ERROR: invalid filter range [%s]", range));
+ ctx->filter_low_id = 0;
+ ctx->filter_high_id = 0;
+ }
+ }
+
+ if (params && *params) {
+ /* assume location is the only parameter */
+ ctx->url = talloc_strdup(ctx, params);
+ } else {
+ tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
+
+ if ( ! tmp) {
+ DEBUG(1, ("ERROR: missing idmap ldap url\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ ctx->url = talloc_strdup(ctx, tmp);
+ }
+ CHECK_ALLOC_DONE(ctx->url);
+
+ tmp = lp_ldap_idmap_suffix();
+ if ( ! tmp || ! *tmp) {
+ tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
+ }
+ if ( ! tmp) {
+ tmp = lp_ldap_suffix();
+ if (tmp) {
+ DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
+ DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
+ } else {
+ DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ }
+ ctx->suffix = talloc_strdup(ctx, tmp);
+ CHECK_ALLOC_DONE(ctx->suffix);
+
+ ret = smbldap_init(ctx, ctx->url, &ctx->smbldap_state);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
+ goto done;
+ }
+
+ ret = get_credentials( ctx, ctx->smbldap_state, config_option,
+ dom, &ctx->user_dn );
+ if ( !NT_STATUS_IS_OK(ret) ) {
+ DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
+ "credentials (%s)\n", nt_errstr(ret)));
+ goto done;
+ }
+
+ /* set the destructor on the context, so that resource are properly
+ freed if the contexts is released */
+
+ talloc_set_destructor(ctx, idmap_ldap_close_destructor);
+
+ dom->private_data = ctx;
+
+ talloc_free(config_option);
+ return NT_STATUS_OK;
+
+/*failed */
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+/* max number of ids requested per batch query */
+#define IDMAP_LDAP_MAX_IDS 30
+
+/**********************************
+ lookup a set of unix ids.
+**********************************/
+
+/* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
+static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
+{
+ int i;
+
+ for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
+ if (maps[i] == NULL) { /* end of the run */
+ return NULL;
+ }
+ if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
+ return maps[i];
+ }
+ }
+
+ return NULL;
+}
+
+static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *memctx;
+ struct idmap_ldap_context *ctx;
+ LDAPMessage *result = NULL;
+ const char *uidNumber;
+ const char *gidNumber;
+ const char **attr_list;
+ char *filter = NULL;
+ BOOL multi = False;
+ int idx = 0;
+ int bidx = 0;
+ int count;
+ int rc;
+ int i;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
+
+ memctx = talloc_new(ctx);
+ if ( ! memctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
+ gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
+
+ attr_list = get_attr_list(ctx, sidmap_attr_list);
+
+ if ( ! ids[1]) {
+ /* if we are requested just one mapping use the simple filter */
+
+ filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
+ LDAP_OBJ_IDMAP_ENTRY,
+ (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
+ (unsigned long)ids[0]->xid.id);
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]\n", filter));
+ } else {
+ /* multiple mappings */
+ multi = True;
+ }
+
+again:
+ if (multi) {
+
+ talloc_free(filter);
+ filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
+ CHECK_ALLOC_DONE(filter);
+
+ bidx = idx;
+ for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
+ filter = talloc_asprintf_append(filter, "(%s=%lu)",
+ (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
+ (unsigned long)ids[idx]->xid.id);
+ CHECK_ALLOC_DONE(filter);
+ }
+ filter = talloc_asprintf_append(filter, "))");
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]\n", filter));
+ } else {
+ bidx = 0;
+ idx = 1;
+ }
+
+ rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
+ filter, attr_list, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
+
+ if (count == 0) {
+ DEBUG(10, ("NO SIDs found\n"));
+ }
+
+ for (i = 0; i < count; i++) {
+ LDAPMessage *entry = NULL;
+ char *sidstr = NULL;
+ char *tmp = NULL;
+ enum id_type type;
+ struct id_map *map;
+ uint32_t id;
+
+ if (i == 0) { /* first entry */
+ entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
+ } else { /* following ones */
+ entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
+ }
+ if ( ! entry) {
+ DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
+ continue;
+ }
+
+ /* first check if the SID is present */
+ sidstr = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, LDAP_ATTRIBUTE_SID, memctx);
+ if ( ! sidstr) { /* no sid, skip entry */
+ DEBUG(2, ("WARNING SID not found on entry\n"));
+ continue;
+ }
+
+ /* now try to see if it is a uid, if not try with a gid
+ * (gid is more common, but in case both uidNumber and
+ * gidNumber are returned the SID is mapped to the uid not the gid) */
+ type = ID_TYPE_UID;
+ tmp = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, uidNumber, memctx);
+ if ( ! tmp) {
+ type = ID_TYPE_GID;
+ tmp = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, gidNumber, memctx);
+ }
+ if ( ! tmp) { /* wow very strange entry, how did it match ? */
+ DEBUG(5, ("Unprobable match on (%s), no uidNumber, nor gidNumber returned\n", sidstr));
+ TALLOC_FREE(sidstr);
+ continue;
+ }
+
+ id = strtoul(tmp, NULL, 10);
+ if ((id == 0) ||
+ (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ id, ctx->filter_low_id, ctx->filter_high_id));
+ TALLOC_FREE(sidstr);
+ TALLOC_FREE(tmp);
+ continue;
+ }
+ TALLOC_FREE(tmp);
+
+ map = find_map_by_id(&ids[bidx], type, id);
+ if (!map) {
+ DEBUG(2, ("WARNING: couldn't match sid (%s) with requested ids\n", sidstr));
+ TALLOC_FREE(sidstr);
+ continue;
+ }
+
+ if ( ! string_to_sid(map->sid, sidstr)) {
+ DEBUG(2, ("ERROR: Invalid SID on entry\n"));
+ TALLOC_FREE(sidstr);
+ continue;
+ }
+ TALLOC_FREE(sidstr);
+
+ /* mapped */
+ map->status = ID_MAPPED;
+
+ DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
+ }
+
+ /* free the ldap results */
+ if (result) {
+ ldap_msgfree(result);
+ result = NULL;
+ }
+
+ if (multi && ids[idx]) { /* still some values to map */
+ goto again;
+ }
+
+ ret = NT_STATUS_OK;
+
+
+ /* mark all unknwon ones as unmapped */
+ for (i = 0; ids[i]; i++) {
+ if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+ }
+
+done:
+ talloc_free(memctx);
+ return ret;
+}
+
+/**********************************
+ lookup a set of sids.
+**********************************/
+
+/* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
+static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
+{
+ int i;
+
+ for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
+ if (maps[i] == NULL) { /* end of the run */
+ return NULL;
+ }
+ if (sid_equal(maps[i]->sid, sid)) {
+ return maps[i];
+ }
+ }
+
+ return NULL;
+}
+
+static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *memctx;
+ struct idmap_ldap_context *ctx;
+ LDAPMessage *result = NULL;
+ const char *uidNumber;
+ const char *gidNumber;
+ const char **attr_list;
+ char *filter = NULL;
+ BOOL multi = False;
+ int idx = 0;
+ int bidx = 0;
+ int count;
+ int rc;
+ int i;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
+
+ memctx = talloc_new(ctx);
+ if ( ! memctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
+ gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
+
+ attr_list = get_attr_list(ctx, sidmap_attr_list);
+
+ if ( ! ids[1]) {
+ /* if we are requested just one mapping use the simple filter */
+
+ filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_IDMAP_ENTRY,
+ LDAP_ATTRIBUTE_SID,
+ sid_string_static(ids[0]->sid));
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]\n", filter));
+ } else {
+ /* multiple mappings */
+ multi = True;
+ }
+
+again:
+ if (multi) {
+
+ TALLOC_FREE(filter);
+ filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
+ CHECK_ALLOC_DONE(filter);
+
+ bidx = idx;
+ for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
+ filter = talloc_asprintf_append(filter, "(%s=%s)",
+ LDAP_ATTRIBUTE_SID,
+ sid_string_static(ids[idx]->sid));
+ CHECK_ALLOC_DONE(filter);
+ }
+ filter = talloc_asprintf_append(filter, "))");
+ CHECK_ALLOC_DONE(filter);
+ DEBUG(10, ("Filter: [%s]", filter));
+ } else {
+ bidx = 0;
+ idx = 1;
+ }
+
+ rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
+ filter, attr_list, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc)));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
+
+ if (count == 0) {
+ DEBUG(10, ("NO SIDs found\n"));
+ }
+
+ for (i = 0; i < count; i++) {
+ LDAPMessage *entry = NULL;
+ char *sidstr = NULL;
+ char *tmp = NULL;
+ enum id_type type;
+ struct id_map *map;
+ DOM_SID sid;
+ uint32_t id;
+
+ if (i == 0) { /* first entry */
+ entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
+ } else { /* following ones */
+ entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
+ }
+
+ /* first check if the SID is present */
+ sidstr = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, LDAP_ATTRIBUTE_SID, memctx);
+ if ( ! sidstr) { /* no sid ??, skip entry */
+ DEBUG(2, ("WARNING SID not found on entry\n"));
+ continue;
+ }
+
+ if ( ! string_to_sid(&sid, sidstr)) {
+ DEBUG(2, ("ERROR: Invalid SID on entry\n"));
+ TALLOC_FREE(sidstr);
+ continue;
+ }
+
+ map = find_map_by_sid(&ids[bidx], &sid);
+ if (!map) {
+ DEBUG(2, ("WARNING: couldn't find entry sid (%s) in ids", sidstr));
+ TALLOC_FREE(sidstr);
+ continue;
+ }
+
+ TALLOC_FREE(sidstr);
+
+ /* now try to see if it is a uid, if not try with a gid
+ * (gid is more common, but in case both uidNumber and
+ * gidNumber are returned the SID is mapped to the uid not the gid) */
+ type = ID_TYPE_UID;
+ tmp = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, uidNumber, memctx);
+ if ( ! tmp) {
+ type = ID_TYPE_GID;
+ tmp = smbldap_talloc_single_attribute(
+ ctx->smbldap_state->ldap_struct,
+ entry, gidNumber, memctx);
+ }
+ if ( ! tmp) { /* no ids ?? */
+ DEBUG(5, ("no uidNumber, nor gidNumber attributes found\n"));
+ continue;
+ }
+
+ id = strtoul(tmp, NULL, 10);
+ if ((id == 0) ||
+ (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ id, ctx->filter_low_id, ctx->filter_high_id));
+ TALLOC_FREE(tmp);
+ continue;
+ }
+ TALLOC_FREE(tmp);
+
+ /* mapped */
+ map->xid.type = type;
+ map->xid.id = id;
+ map->status = ID_MAPPED;
+
+ DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
+ }
+
+ /* free the ldap results */
+ if (result) {
+ ldap_msgfree(result);
+ result = NULL;
+ }
+
+ if (multi && ids[idx]) { /* still some values to map */
+ goto again;
+ }
+
+ ret = NT_STATUS_OK;
+
+ /* mark all unknwon ones as unmapped */
+ for (i = 0; ids[i]; i++) {
+ if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+ }
+
+done:
+ talloc_free(memctx);
+ return ret;
+}
+
+/**********************************
+ set a mapping.
+**********************************/
+
+/* TODO: change this: This function cannot be called to modify a mapping, only set a new one */
+
+static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *memctx;
+ struct idmap_ldap_context *ctx;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ const char *type;
+ char *id_str;
+ char *sid;
+ char *dn;
+ int rc = -1;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
+
+ switch(map->xid.type) {
+ case ID_TYPE_UID:
+ type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_UIDNUMBER);
+ break;
+
+ case ID_TYPE_GID:
+ type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_GIDNUMBER);
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ memctx = talloc_new(ctx);
+ if ( ! memctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
+ CHECK_ALLOC_DONE(id_str);
+
+ sid = talloc_strdup(memctx, sid_string_static(map->sid));
+ CHECK_ALLOC_DONE(sid);
+
+ dn = talloc_asprintf(memctx, "%s=%s,%s",
+ get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
+ sid,
+ ctx->suffix);
+ CHECK_ALLOC_DONE(dn);
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY);
+
+ smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, type, id_str);
+
+ smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid);
+
+ if ( ! mods) {
+ DEBUG(2, ("ERROR: No mods?\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* TODO: remove conflicting mappings! */
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
+
+ DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
+
+ rc = smbldap_add(ctx->smbldap_state, dn, mods);
+ ldap_mods_free(mods, True);
+
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(ctx->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu mapping [%s]\n",
+ sid, (unsigned long)map->xid.id, type));
+ DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
+ ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
+ sid, (unsigned long)map->xid.id, type));
+
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(memctx);
+ return ret;
+}
+
+/**********************************
+ remove a mapping.
+**********************************/
+
+static NTSTATUS idmap_ldap_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+/**********************************
+ Close the idmap ldap instance
+**********************************/
+
+static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
+{
+ struct idmap_ldap_context *ctx;
+
+ if (dom->private_data) {
+ ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
+
+ talloc_free(ctx);
+ dom->private_data = NULL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static struct idmap_methods idmap_ldap_methods = {
+
+ .init = idmap_ldap_db_init,
+ .unixids_to_sids = idmap_ldap_unixids_to_sids,
+ .sids_to_unixids = idmap_ldap_sids_to_unixids,
+ .set_mapping = idmap_ldap_set_mapping,
+ .remove_mapping = idmap_ldap_remove_mapping,
+ /* .dump_data = TODO */
+ .close_fn = idmap_ldap_close
+};
+
+static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
+
+ .init = idmap_ldap_alloc_init,
+ .allocate_id = idmap_ldap_allocate_id,
+ .get_id_hwm = idmap_ldap_get_hwm,
+ .set_id_hwm = idmap_ldap_set_hwm,
+ .close_fn = idmap_ldap_alloc_close,
+ /* .dump_data = TODO */
+};
+
+NTSTATUS idmap_alloc_ldap_init(void)
+{
+ return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_alloc_methods);
+}
+
+NTSTATUS idmap_ldap_init(void)
+{
+ NTSTATUS ret;
+
+ /* FIXME: bad hack to actually register also the alloc_ldap module without changining configure.in */
+ ret = idmap_alloc_ldap_init();
+ if (! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_methods);
+}
+
diff --git a/source/nsswitch/idmap_nss.c b/source/nsswitch/idmap_nss.c
new file mode 100644
index 00000000000..3cd8a8e8eae
--- /dev/null
+++ b/source/nsswitch/idmap_nss.c
@@ -0,0 +1,215 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap PASSDB backend
+
+ Copyright (C) Simo Sorce 2006
+
+ 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 "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/*****************************
+ Initialise idmap database.
+*****************************/
+
+static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom, const char *compat_params)
+{
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of unix ids.
+**********************************/
+
+static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ TALLOC_CTX *ctx;
+ int i;
+
+ ctx = talloc_new(dom);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; ids[i]; i++) {
+ struct passwd *pw;
+ struct group *gr;
+ const char *name;
+ enum lsa_SidType type;
+ BOOL ret;
+
+ switch (ids[i]->xid.type) {
+ case ID_TYPE_UID:
+ pw = getpwuid((uid_t)ids[i]->xid.id);
+
+ if (!pw) {
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+ name = pw->pw_name;
+ break;
+ case ID_TYPE_GID:
+ gr = getgrgid((gid_t)ids[i]->xid.id);
+
+ if (!gr) {
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+ name = gr->gr_name;
+ break;
+ default: /* ?? */
+ ids[i]->status = ID_UNKNOWN;
+ continue;
+ }
+
+ /* by default calls to winbindd are disabled
+ the following call will not recurse so this is safe */
+ winbind_on();
+ /* Lookup name from PDC using lsa_lookup_names() */
+ ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
+ winbind_off();
+
+ if (!ret) {
+ /* TODO: how do we know if the name is really not mapped,
+ * or something just failed ? */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ switch (type) {
+ case SID_NAME_USER:
+ if (ids[i]->xid.type == ID_TYPE_UID) {
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ if (ids[i]->xid.type == ID_TYPE_GID) {
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+
+ default:
+ ids[i]->status = ID_UNKNOWN;
+ break;
+ }
+ }
+
+
+ talloc_free(ctx);
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of sids.
+**********************************/
+
+static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ TALLOC_CTX *ctx;
+ int i;
+
+ ctx = talloc_new(dom);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; ids[i]; i++) {
+ struct passwd *pw;
+ struct group *gr;
+ enum lsa_SidType type;
+ const char *dom_name = NULL;
+ const char *name = NULL;
+ BOOL ret;
+
+ /* by default calls to winbindd are disabled
+ the following call will not recurse so this is safe */
+ winbind_on();
+ ret = winbind_lookup_sid(ctx, ids[i]->sid, &dom_name, &name, &type);
+ winbind_off();
+
+ if (!ret) {
+ /* TODO: how do we know if the name is really not mapped,
+ * or something just failed ? */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ switch (type) {
+ case SID_NAME_USER:
+
+ /* this will find also all lower case name and use username level */
+
+ pw = Get_Pwnam(name);
+ if (pw) {
+ ids[i]->xid.id = pw->pw_uid;
+ ids[i]->xid.type = ID_TYPE_UID;
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+
+ gr = getgrnam(name);
+ if (gr) {
+ ids[i]->xid.id = gr->gr_gid;
+ ids[i]->xid.type = ID_TYPE_GID;
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+
+ default:
+ ids[i]->status = ID_UNKNOWN;
+ break;
+ }
+ }
+
+ talloc_free(ctx);
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Close the idmap tdb instance
+**********************************/
+
+static NTSTATUS idmap_nss_close(struct idmap_domain *dom)
+{
+ return NT_STATUS_OK;
+}
+
+static struct idmap_methods nss_methods = {
+
+ .init = idmap_nss_int_init,
+ .unixids_to_sids = idmap_nss_unixids_to_sids,
+ .sids_to_unixids = idmap_nss_sids_to_unixids,
+ .close_fn = idmap_nss_close
+};
+
+NTSTATUS idmap_nss_init(void)
+{
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "nss", &nss_methods);
+}
diff --git a/source/nsswitch/idmap_passdb.c b/source/nsswitch/idmap_passdb.c
new file mode 100644
index 00000000000..a5f8a084b3a
--- /dev/null
+++ b/source/nsswitch/idmap_passdb.c
@@ -0,0 +1,131 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap PASSDB backend
+
+ Copyright (C) Simo Sorce 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/*****************************
+ Initialise idmap database.
+*****************************/
+
+static NTSTATUS idmap_pdb_init(struct idmap_domain *dom, const char *compat_params)
+{
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of unix ids.
+**********************************/
+
+static NTSTATUS idmap_pdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ int i;
+
+ for (i = 0; ids[i]; i++) {
+
+ /* unmapped by default */
+ ids[i]->status = ID_UNMAPPED;
+
+ switch (ids[i]->xid.type) {
+ case ID_TYPE_UID:
+ if (pdb_uid_to_sid((uid_t)ids[i]->xid.id, ids[i]->sid)) {
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+ case ID_TYPE_GID:
+ if (pdb_gid_to_sid((gid_t)ids[i]->xid.id, ids[i]->sid)) {
+ ids[i]->status = ID_MAPPED;
+ }
+ break;
+ default: /* ?? */
+ ids[i]->status = ID_UNKNOWN;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of sids.
+**********************************/
+
+static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ int i;
+
+ for (i = 0; ids[i]; i++) {
+ enum lsa_SidType type;
+ union unid_t id;
+
+ if (pdb_sid_to_id(ids[i]->sid, &id, &type)) {
+ switch (type) {
+ case SID_NAME_USER:
+ ids[i]->xid.id = id.uid;
+ ids[i]->xid.type = ID_TYPE_UID;
+ ids[i]->status = ID_MAPPED;
+ break;
+
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ ids[i]->xid.id = id.gid;
+ ids[i]->xid.type = ID_TYPE_GID;
+ ids[i]->status = ID_MAPPED;
+ break;
+
+ default: /* ?? */
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNKNOWN;
+ break;
+ }
+ } else {
+ /* Query Failed */
+ ids[i]->status = ID_UNMAPPED;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Close the idmap tdb instance
+**********************************/
+
+static NTSTATUS idmap_pdb_close(struct idmap_domain *dom)
+{
+ return NT_STATUS_OK;
+}
+
+static struct idmap_methods passdb_methods = {
+
+ .init = idmap_pdb_init,
+ .unixids_to_sids = idmap_pdb_unixids_to_sids,
+ .sids_to_unixids = idmap_pdb_sids_to_unixids,
+ .close_fn =idmap_pdb_close
+};
+
+NTSTATUS idmap_passdb_init(void)
+{
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "passdb", &passdb_methods);
+}
diff --git a/source/nsswitch/idmap_rid.c b/source/nsswitch/idmap_rid.c
new file mode 100644
index 00000000000..298d6fed355
--- /dev/null
+++ b/source/nsswitch/idmap_rid.c
@@ -0,0 +1,298 @@
+/*
+ * idmap_rid: static map between Active Directory/NT RIDs and RFC 2307 accounts
+ * Copyright (C) Guenther Deschner, 2004
+ * Copyright (C) Sumit Bose, 2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "includes.h"
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+struct idmap_rid_context {
+ const char *domain_name;
+ uint32_t low_id;
+ uint32_t high_id;
+ uint32_t base_rid;
+};
+
+/******************************************************************************
+ compat params can't be used because of the completely different way
+ we support multiple domains in the new idmap
+ *****************************************************************************/
+
+static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom, const char *compat_params)
+{
+ NTSTATUS ret;
+ struct idmap_rid_context *ctx;
+ char *config_option = NULL;
+ const char *range;
+
+ if ( (ctx = talloc_zero(dom, struct idmap_rid_context)) == NULL ) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+ if ( ! config_option) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if ( !range ||
+ (sscanf(range, "%u - %u", &ctx->low_id, &ctx->high_id) != 2) ||
+ (ctx->low_id > ctx->high_id))
+ {
+ ctx->low_id = 0;
+ ctx->high_id = 0;
+ }
+
+ if ( !ctx->low_id || !ctx->high_id ) {
+ DEBUG(1, ("ERROR: Invalid configuration, ID range missing\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto failed;
+ }
+
+ ctx->base_rid = lp_parm_int(-1, config_option, "base_rid", 0);
+ ctx->domain_name = talloc_strdup( ctx, dom->name );
+
+ dom->private_data = ctx;
+
+ talloc_free(config_option);
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(ctx);
+ return ret;
+}
+
+static NTSTATUS idmap_rid_id_to_sid(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map)
+{
+ const char *domname, *name;
+ enum lsa_SidType sid_type;
+ BOOL ret;
+ struct winbindd_domain *domain;
+
+ /* apply filters before checking */
+ if ((map->xid.id < ctx->low_id) || (map->xid.id > ctx->high_id)) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->low_id, ctx->high_id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ if ( (domain = find_domain_from_name_noinit(ctx->domain_name)) == NULL ) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ sid_compose(map->sid, &domain->sid, map->xid.id - ctx->low_id + ctx->base_rid);
+
+ /* by default calls to winbindd are disabled
+ the following call will not recurse so this is safe */
+ winbind_on();
+ ret = winbind_lookup_sid(memctx, map->sid, &domname, &name, &sid_type);
+ winbind_off();
+
+ if (ret) {
+ switch (sid_type) {
+ case SID_NAME_USER:
+ if (map->xid.type != ID_TYPE_UID) {
+ /* wrong type */
+ map->status = ID_UNMAPPED;
+ DEBUG(5, ("Resulting SID is of wrong ID type\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ break;
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ if (map->xid.type != ID_TYPE_GID) {
+ /* wrong type */
+ map->status = ID_UNMAPPED;
+ DEBUG(5, ("Resulting SID is of wrong ID type\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ break;
+ default:
+ /* invalid sid?? */
+ map->status = ID_UNKNOWN;
+ DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ } else {
+ /* TODO: how do we known if the lookup was negative
+ * or something just failed? */
+ map->status = ID_UNMAPPED;
+ DEBUG(2, ("Failed: to resolve SID\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ map->status = ID_MAPPED;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Single sid to id lookup function.
+**********************************/
+
+static NTSTATUS idmap_rid_sid_to_id(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map)
+{
+ const char *domname, *name;
+ enum lsa_SidType sid_type;
+ uint32_t rid;
+ BOOL ret;
+
+ sid_peek_rid(map->sid, &rid);
+ map->xid.id = rid - ctx->base_rid + ctx->low_id;
+
+ /* by default calls to winbindd are disabled
+ the following call will not recurse so this is safe */
+ winbind_on();
+ /* check if this is a valid SID and set the type */
+ ret = winbind_lookup_sid(memctx, map->sid, &domname, &name, &sid_type);
+ winbind_off();
+
+ if (ret) {
+ switch (sid_type) {
+ case SID_NAME_USER:
+ map->xid.type = ID_TYPE_UID;
+ break;
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ map->xid.type = ID_TYPE_GID;
+ break;
+ default:
+ /* invalid sid, let's just leave it unmapped */
+ DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
+ map->status = ID_UNKNOWN;
+ return NT_STATUS_NONE_MAPPED;
+ }
+ } else {
+ /* TODO: how do we known if the lookup was negative
+ * or something just failed? */
+ map->status = ID_UNMAPPED;
+ DEBUG(2, ("Failed: to resolve SID\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* apply filters before returning result */
+ if ((map->xid.id < ctx->low_id) || (map->xid.id > ctx->high_id)) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->low_id, ctx->high_id));
+ map->status = ID_UNMAPPED;
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ map->status = ID_MAPPED;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of unix ids.
+**********************************/
+
+static NTSTATUS idmap_rid_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_rid_context *ridctx;
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ int i;
+
+ ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context);
+
+ ctx = talloc_new(dom);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; ids[i]; i++) {
+
+ ret = idmap_rid_id_to_sid(ctx, ridctx, ids[i]);
+
+ if (( ! NT_STATUS_IS_OK(ret)) &&
+ ( ! NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
+ /* some fatal error occurred, log it */
+ DEBUG(3, ("Unexpected error resolving an ID (%d)\n", ids[i]->xid.id));
+ }
+ }
+
+ talloc_free(ctx);
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ lookup a set of sids.
+**********************************/
+
+static NTSTATUS idmap_rid_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_rid_context *ridctx;
+ TALLOC_CTX *ctx;
+ NTSTATUS ret;
+ int i;
+
+ ridctx = talloc_get_type(dom->private_data, struct idmap_rid_context);
+
+ ctx = talloc_new(dom);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; ids[i]; i++) {
+
+ ret = idmap_rid_sid_to_id(ctx, ridctx, ids[i]);
+
+ if (( ! NT_STATUS_IS_OK(ret)) &&
+ ( ! NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
+ /* some fatal error occurred, log it */
+ DEBUG(3, ("Unexpected error resolving a SID (%s)\n",
+ sid_string_static(ids[i]->sid)));
+ }
+ }
+
+ talloc_free(ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS idmap_rid_close(struct idmap_domain *dom)
+{
+ if (dom->private_data) {
+ TALLOC_FREE(dom->private_data);
+ }
+ return NT_STATUS_OK;
+}
+
+static struct idmap_methods rid_methods = {
+ .init = idmap_rid_initialize,
+ .unixids_to_sids = idmap_rid_unixids_to_sids,
+ .sids_to_unixids = idmap_rid_sids_to_unixids,
+ .close_fn = idmap_rid_close
+};
+
+NTSTATUS idmap_rid_init(void)
+{
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rid", &rid_methods);
+}
+
diff --git a/source/nsswitch/idmap_tdb.c b/source/nsswitch/idmap_tdb.c
new file mode 100644
index 00000000000..c21c066fea1
--- /dev/null
+++ b/source/nsswitch/idmap_tdb.c
@@ -0,0 +1,1214 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap TDB backend
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Jeremy Allison 2006
+ Copyright (C) Simo Sorce 2003-2006
+
+ 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 "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* High water mark keys */
+#define HWM_GROUP "GROUP HWM"
+#define HWM_USER "USER HWM"
+
+static struct idmap_tdb_state {
+
+ /* User and group id pool */
+ uid_t low_uid, high_uid; /* Range of uids to allocate */
+ gid_t low_gid, high_gid; /* Range of gids to allocate */
+
+} idmap_tdb_state;
+
+/*****************************************************************************
+ For idmap conversion: convert one record to new format
+ Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid
+ instead of the SID.
+*****************************************************************************/
+static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state)
+{
+ struct winbindd_domain *domain;
+ char *p;
+ DOM_SID sid;
+ uint32 rid;
+ fstring keystr;
+ fstring dom_name;
+ TDB_DATA key2;
+ BOOL *failed = (BOOL *)state;
+
+ DEBUG(10,("Converting %s\n", key.dptr));
+
+ p = strchr(key.dptr, '/');
+ if (!p)
+ return 0;
+
+ *p = 0;
+ fstrcpy(dom_name, key.dptr);
+ *p++ = '/';
+
+ domain = find_domain_from_name(dom_name);
+ if (domain == NULL) {
+ /* We must delete the old record. */
+ DEBUG(0,("Unable to find domain %s\n", dom_name ));
+ DEBUG(0,("deleting record %s\n", key.dptr ));
+
+ if (tdb_delete(tdb, key) != 0) {
+ DEBUG(0, ("Unable to delete record %s\n", key.dptr));
+ *failed = True;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ rid = atoi(p);
+
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, rid);
+
+ sid_to_string(keystr, &sid);
+ key2.dptr = keystr;
+ key2.dsize = strlen(keystr) + 1;
+
+ if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) {
+ DEBUG(0,("Unable to add record %s\n", key2.dptr ));
+ *failed = True;
+ return -1;
+ }
+
+ if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) {
+ DEBUG(0,("Unable to update record %s\n", data.dptr ));
+ *failed = True;
+ return -1;
+ }
+
+ if (tdb_delete(tdb, key) != 0) {
+ DEBUG(0,("Unable to delete record %s\n", key.dptr ));
+ *failed = True;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Convert the idmap database from an older version.
+*****************************************************************************/
+
+static BOOL idmap_tdb_convert(const char *idmap_name)
+{
+ int32 vers;
+ BOOL bigendianheader;
+ BOOL failed = False;
+ TDB_CONTEXT *idmap_tdb;
+
+ if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
+ TDB_DEFAULT, O_RDWR,
+ 0600))) {
+ DEBUG(0, ("Unable to open idmap database\n"));
+ return False;
+ }
+
+ bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False;
+
+ vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
+
+ if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
+ /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
+ /*
+ * high and low records were created on a
+ * big endian machine and will need byte-reversing.
+ */
+
+ int32 wm;
+
+ wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
+
+ if (wm != -1) {
+ wm = IREV(wm);
+ } else {
+ wm = idmap_tdb_state.low_uid;
+ }
+
+ if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
+ DEBUG(0, ("Unable to byteswap user hwm in idmap database\n"));
+ tdb_close(idmap_tdb);
+ return False;
+ }
+
+ wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
+ if (wm != -1) {
+ wm = IREV(wm);
+ } else {
+ wm = idmap_tdb_state.low_gid;
+ }
+
+ if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
+ DEBUG(0, ("Unable to byteswap group hwm in idmap database\n"));
+ tdb_close(idmap_tdb);
+ return False;
+ }
+ }
+
+ /* the old format stored as DOMAIN/rid - now we store the SID direct */
+ tdb_traverse(idmap_tdb, convert_fn, &failed);
+
+ if (failed) {
+ DEBUG(0, ("Problem during conversion\n"));
+ tdb_close(idmap_tdb);
+ return False;
+ }
+
+ if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
+ DEBUG(0, ("Unable to dtore idmap version in databse\n"));
+ tdb_close(idmap_tdb);
+ return False;
+ }
+
+ tdb_close(idmap_tdb);
+ return True;
+}
+
+/*****************************************************************************
+ Convert the idmap database from an older version if necessary
+*****************************************************************************/
+
+BOOL idmap_tdb_upgrade(TALLOC_CTX *ctx, const char *tdbfile)
+{
+ char *backup_name;
+
+ DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n"));
+
+ backup_name = talloc_asprintf(ctx, "%s.bak", tdbfile);
+ if ( ! backup_name) {
+ DEBUG(0, ("Out of memory!\n"));
+ return False;
+ }
+
+ if (backup_tdb(tdbfile, backup_name, 0) != 0) {
+ DEBUG(0, ("Could not backup idmap database\n"));
+ talloc_free(backup_name);
+ return False;
+ }
+
+ talloc_free(backup_name);
+ return idmap_tdb_convert(tdbfile);
+}
+
+/* WARNING: We can't open a tdb twice inthe same process, for that reason
+ * I'm going to use a hack with open ref counts to open the winbindd_idmap.tdb
+ * only once. We will later decide whether to split the db in multiple files
+ * or come up with a better solution to share them. */
+
+static TDB_CONTEXT *idmap_tdb_common_ctx;
+static int idmap_tdb_open_ref_count = 0;
+
+static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *ctx;
+ SMB_STRUCT_STAT stbuf;
+ char *tdbfile = NULL;
+ int32 version;
+ BOOL tdb_is_new = False;
+
+ if (idmap_tdb_open_ref_count) { /* the tdb has already been opened */
+ idmap_tdb_open_ref_count++;
+ *tdbctx = idmap_tdb_common_ctx;
+ return NT_STATUS_OK;
+ }
+
+ /* use our own context here */
+ ctx = talloc_new(memctx);
+ if (!ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* use the old database if present */
+ tdbfile = talloc_strdup(ctx, lock_path("winbindd_idmap.tdb"));
+ if (!tdbfile) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (!file_exist(tdbfile, &stbuf)) {
+ tdb_is_new = True;
+ }
+
+ DEBUG(10,("Opening tdbfile %s\n", tdbfile ));
+
+ /* Open idmap repository */
+ if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) {
+ DEBUG(0, ("Unable to open idmap database\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (tdb_is_new) {
+ /* the file didn't existed before opening it, let's
+ * store idmap version as nobody else yet opened and
+ * stored it. I do not like this method but didn't
+ * found a way to understand if an opened tdb have
+ * been just created or not --- SSS */
+ tdb_store_int32(idmap_tdb_common_ctx, "IDMAP_VERSION", IDMAP_VERSION);
+ }
+
+ /* check against earlier versions */
+ version = tdb_fetch_int32(idmap_tdb_common_ctx, "IDMAP_VERSION");
+ if (version != IDMAP_VERSION) {
+
+ /* backup_tdb expects the tdb not to be open */
+ tdb_close(idmap_tdb_common_ctx);
+
+ if ( ! idmap_tdb_upgrade(ctx, tdbfile)) {
+
+ DEBUG(0, ("Unable to open idmap database, it's in an old formati, and upgrade failed!\n"));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ goto done;
+ }
+
+ /* Re-Open idmap repository */
+ if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) {
+ DEBUG(0, ("Unable to open idmap database\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ }
+
+ *tdbctx = idmap_tdb_common_ctx;
+ idmap_tdb_open_ref_count++;
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ctx);
+ return ret;
+}
+
+ /* NEVER use tdb_close() except for the conversion routines that are guaranteed
+ * to run only when the database is opened the first time, always use this function. */
+
+BOOL idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx)
+{
+ if (tdbctx != idmap_tdb_common_ctx) {
+ DEBUG(0, ("ERROR: Invalid tdb context!"));
+ return False;
+ }
+
+ idmap_tdb_open_ref_count--;
+ if (idmap_tdb_open_ref_count) {
+ return True;
+ }
+
+ return tdb_close(idmap_tdb_common_ctx);
+}
+
+/**********************************************************************
+ IDMAP ALLOC TDB BACKEND
+**********************************************************************/
+
+static TDB_CONTEXT *idmap_alloc_tdb;
+
+/**********************************
+ Initialise idmap alloc database.
+**********************************/
+
+static NTSTATUS idmap_tdb_alloc_init( const char *params )
+{
+ NTSTATUS ret;
+ TALLOC_CTX *ctx;
+ const char *range;
+ uid_t low_uid = 0;
+ uid_t high_uid = 0;
+ gid_t low_gid = 0;
+ gid_t high_gid = 0;
+
+ /* use our own context here */
+ ctx = talloc_new(NULL);
+ if (!ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = idmap_tdb_open_db(ctx, &idmap_alloc_tdb);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ talloc_free(ctx);
+ return ret;
+ }
+
+ talloc_free(ctx);
+
+ /* load ranges */
+ idmap_tdb_state.low_uid = 0;
+ idmap_tdb_state.high_uid = 0;
+ idmap_tdb_state.low_gid = 0;
+ idmap_tdb_state.high_gid = 0;
+
+ range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
+ if (range && range[0]) {
+ unsigned low_id, high_id;
+
+ if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
+ if (low_id < high_id) {
+ idmap_tdb_state.low_gid = idmap_tdb_state.low_uid = low_id;
+ idmap_tdb_state.high_gid = idmap_tdb_state.high_uid = high_id;
+ } else {
+ DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
+ }
+ } else {
+ DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
+ }
+ }
+
+ /* Create high water marks for group and user id */
+ if (lp_idmap_uid(&low_uid, &high_uid)) {
+ idmap_tdb_state.low_uid = low_uid;
+ idmap_tdb_state.high_uid = high_uid;
+ }
+
+ if (lp_idmap_gid(&low_gid, &high_gid)) {
+ idmap_tdb_state.low_gid = low_gid;
+ idmap_tdb_state.high_gid = high_gid;
+ }
+
+ if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) {
+ DEBUG(1, ("idmap uid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) ||
+ (low_id < idmap_tdb_state.low_uid)) {
+ if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, idmap_tdb_state.low_uid) == -1) {
+ DEBUG(0, ("Unable to initialise user hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) {
+ DEBUG(1, ("idmap gid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) ||
+ (low_id < idmap_tdb_state.low_gid)) {
+ if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, idmap_tdb_state.low_gid) == -1) {
+ DEBUG(0, ("Unable to initialise group hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Allocate a new id.
+**********************************/
+
+static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid)
+{
+ BOOL ret;
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t high_hwm;
+ uint32_t hwm;
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb_state.high_gid;
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* check it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* fetch a new id and increment it */
+ ret = tdb_change_uint32_atomic(idmap_alloc_tdb, hwmkey, &hwm, 1);
+ if (!ret) {
+ DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* recheck it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ xid->id = hwm;
+ DEBUG(10,("New %s = %d\n", hwmtype, hwm));
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Get current highest id.
+**********************************/
+
+static NTSTATUS idmap_tdb_get_hwm(struct unixid *xid)
+{
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t hwm;
+ uint32_t high_hwm;
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb_state.high_gid;
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ xid->id = hwm;
+
+ /* Warn if it is out of range */
+ if (hwm >= high_hwm) {
+ DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Set high id.
+**********************************/
+
+static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid)
+{
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t hwm;
+ uint32_t high_hwm;
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb_state.high_gid;
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ hwm = xid->id;
+
+ if ((hwm = tdb_store_int32(idmap_alloc_tdb, hwmkey, hwm)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* Warn if it is out of range */
+ if (hwm >= high_hwm) {
+ DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************
+ Close the alloc tdb
+**********************************/
+
+static NTSTATUS idmap_tdb_alloc_close(void)
+{
+ if (idmap_alloc_tdb) {
+ if (idmap_tdb_tdb_close(idmap_alloc_tdb) == 0) {
+ return NT_STATUS_OK;
+ } else {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ IDMAP MAPPING TDB BACKEND
+**********************************************************************/
+
+struct idmap_tdb_context {
+ TDB_CONTEXT *tdb;
+ uint32_t filter_low_id;
+ uint32_t filter_high_id;
+};
+
+/*****************************
+ Initialise idmap database.
+*****************************/
+
+static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *compat_params)
+{
+ NTSTATUS ret;
+ struct idmap_tdb_context *ctx;
+ char *config_option = NULL;
+ const char *range;
+
+ ctx = talloc(dom, struct idmap_tdb_context);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+ if ( ! config_option) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
+ ret = idmap_tdb_open_db(ctx, &ctx->tdb);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ goto failed;
+ }
+
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if (( ! range) ||
+ (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
+ (ctx->filter_low_id > ctx->filter_high_id)) {
+ ctx->filter_low_id = 0;
+ ctx->filter_high_id = 0;
+ }
+
+ dom->private_data = ctx;
+
+ talloc_free(config_option);
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(ctx);
+ return ret;
+}
+
+/**********************************
+ Single id to sid lookup function.
+**********************************/
+
+static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA key, data;
+
+ if (!ctx || !map) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* apply filters before checking */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ key.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ key.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* final SAFE_FREE safe */
+ data.dptr = NULL;
+
+ if (key.dptr == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ key.dsize = strlen(key.dptr) + 1;
+
+ DEBUG(10,("Fetching record %s\n", key.dptr));
+
+ /* Check if the mapping exists */
+ data = tdb_fetch(ctx->tdb, key);
+
+ if (!data.dptr) {
+ DEBUG(10,("Record %s not found\n", key.dptr));
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ if (!string_to_sid(map->sid, data.dptr)) {
+ DEBUG(10,("INVALID SID (%s) in record %s\n",
+ data.dptr, key.dptr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ goto done;
+ }
+
+ DEBUG(10,("Found record %s -> %s\n", key.dptr, data.dptr));
+ ret = NT_STATUS_OK;
+
+done:
+ SAFE_FREE(data.dptr);
+ talloc_free(key.dptr);
+ return ret;
+}
+
+/**********************************
+ Single sid to id lookup function.
+**********************************/
+
+static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA key, data;
+ unsigned long rec_id = 0;
+
+ if ((key.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ key.dsize = strlen(key.dptr) + 1;
+
+ DEBUG(10,("Fetching record %s\n", key.dptr));
+
+ /* Check if sid is present in database */
+ data = tdb_fetch(ctx->tdb, key);
+ if (!data.dptr) {
+ DEBUG(10,("Record %s not found\n", key.dptr));
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* What type of record is this ? */
+ if (sscanf(data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_UID;
+ DEBUG(10,("Found uid record %s -> %s \n", key.dptr, data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else if (sscanf(data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_GID;
+ DEBUG(10,("Found gid record %s -> %s \n", key.dptr, data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else { /* Unknown record type ! */
+ DEBUG(2, ("Found INVALID record %s -> %s\n", key.dptr, data.dptr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ SAFE_FREE(data.dptr);
+
+ /* apply filters before returning result */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ ret = NT_STATUS_NONE_MAPPED;
+ }
+
+done:
+ talloc_free(key.dptr);
+ return ret;
+}
+
+/**********************************
+ lookup a set of unix ids.
+**********************************/
+
+static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb_id_to_sid(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/**********************************
+ lookup a set of sids.
+**********************************/
+
+static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb_sid_to_id(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/**********************************
+ set a mapping.
+**********************************/
+
+static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ struct idmap_tdb_context *ctx;
+ NTSTATUS ret;
+ TDB_DATA ksid, kid, data;
+
+ if (!map || !map->sid) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ksid.dptr = kid.dptr = data.dptr = NULL;
+
+ /* TODO: should we filter a set_mapping using low/high filters ? */
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ kid.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ kid.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (kid.dptr == NULL) {
+ DEBUG(0, ("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ kid.dsize = strlen(kid.dptr) + 1;
+
+ if ((ksid.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ ksid.dsize = strlen(ksid.dptr) + 1;
+
+ DEBUG(10, ("Storing %s <-> %s map\n", ksid.dptr, kid.dptr));
+
+ /* *DELETE* previous mappings if any.
+ * This is done both SID and [U|G]ID passed in */
+
+ /* Lock the record for this SID. */
+ if (tdb_chainlock(ctx->tdb, ksid) != 0) {
+ DEBUG(10,("Failed to lock record %s. Error %s\n",
+ ksid.dptr, tdb_errorstr(ctx->tdb) ));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ data = tdb_fetch(ctx->tdb, ksid);
+ if (data.dptr) {
+ DEBUG(10, ("Deleting existing mapping %s <-> %s\n", data.dptr, ksid.dptr ));
+ tdb_delete(ctx->tdb, data);
+ tdb_delete(ctx->tdb, ksid);
+ SAFE_FREE(data.dptr);
+ }
+
+ data = tdb_fetch(ctx->tdb, kid);
+ if (data.dptr) {
+ DEBUG(10,("Deleting existing mapping %s <-> %s\n", data.dptr, kid.dptr ));
+ tdb_delete(ctx->tdb, data);
+ tdb_delete(ctx->tdb, kid);
+ SAFE_FREE(data.dptr);
+ }
+
+ if (tdb_store(ctx->tdb, ksid, kid, TDB_INSERT) == -1) {
+ DEBUG(0, ("Error storing SID -> ID: %s\n", tdb_errorstr(ctx->tdb)));
+ tdb_chainunlock(ctx->tdb, ksid);
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ if (tdb_store(ctx->tdb, kid, ksid, TDB_INSERT) == -1) {
+ DEBUG(0, ("Error stroing ID -> SID: %s\n", tdb_errorstr(ctx->tdb)));
+ /* try to remove the previous stored SID -> ID map */
+ tdb_delete(ctx->tdb, ksid);
+ tdb_chainunlock(ctx->tdb, ksid);
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ tdb_chainunlock(ctx->tdb, ksid);
+ DEBUG(10,("Stored %s <-> %s\n", ksid.dptr, kid.dptr));
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ksid.dptr);
+ talloc_free(kid.dptr);
+ SAFE_FREE(data.dptr);
+ return ret;
+}
+
+/**********************************
+ remove a mapping.
+**********************************/
+
+static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ struct idmap_tdb_context *ctx;
+ NTSTATUS ret;
+ TDB_DATA ksid, kid, data;
+
+ if (!map || !map->sid) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ksid.dptr = kid.dptr = data.dptr = NULL;
+
+ /* TODO: should we filter a remove_mapping using low/high filters ? */
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ kid.dptr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ kid.dptr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (kid.dptr == NULL) {
+ DEBUG(0, ("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ kid.dsize = strlen(kid.dptr) + 1;
+
+ if ((ksid.dptr = talloc_asprintf(ctx, "%s", sid_string_static(map->sid))) == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ ksid.dsize = strlen(ksid.dptr) + 1;
+
+ DEBUG(10, ("Checking %s <-> %s map\n", ksid.dptr, kid.dptr));
+
+ /* Lock the record for this SID. */
+ if (tdb_chainlock(ctx->tdb, ksid) != 0) {
+ DEBUG(10,("Failed to lock record %s. Error %s\n",
+ ksid.dptr, tdb_errorstr(ctx->tdb) ));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Check if sid is present in database */
+ data = tdb_fetch(ctx->tdb, ksid);
+ if (!data.dptr) {
+ DEBUG(10,("Record %s not found\n", ksid.dptr));
+ tdb_chainunlock(ctx->tdb, ksid);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ /* Check if sid is mapped to the specified ID */
+ if ((data.dsize != kid.dsize) ||
+ (memcmp(data.dptr, kid.dptr, data.dsize) != 0)) {
+ DEBUG(10,("Specified SID does not map to specified ID\n"));
+ DEBUGADD(10,("Actual mapping is %s -> %s\n", ksid.dptr, data.dptr));
+ tdb_chainunlock(ctx->tdb, ksid);
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ DEBUG(10, ("Removing %s <-> %s map\n", ksid.dptr, kid.dptr));
+
+ /* Delete previous mappings. */
+
+ DEBUG(10, ("Deleting existing mapping %s -> %s\n", ksid.dptr, kid.dptr ));
+ tdb_delete(ctx->tdb, ksid);
+
+ DEBUG(10,("Deleting existing mapping %s -> %s\n", kid.dptr, ksid.dptr ));
+ tdb_delete(ctx->tdb, kid);
+
+ tdb_chainunlock(ctx->tdb, ksid);
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ksid.dptr);
+ talloc_free(kid.dptr);
+ SAFE_FREE(data.dptr);
+ return ret;
+}
+
+/**********************************
+ Close the idmap tdb instance
+**********************************/
+
+static NTSTATUS idmap_tdb_close(struct idmap_domain *dom)
+{
+ struct idmap_tdb_context *ctx;
+
+ if (dom->private_data) {
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ if (idmap_tdb_tdb_close(ctx->tdb) == 0) {
+ return NT_STATUS_OK;
+ } else {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+struct dump_data {
+ TALLOC_CTX *memctx;
+ struct id_map **maps;
+ int *num_maps;
+ NTSTATUS ret;
+};
+
+static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, void *pdata)
+{
+ struct dump_data *data = talloc_get_type(pdata, struct dump_data);
+ struct id_map *maps;
+ int num_maps = *data->num_maps;
+
+ /* ignore any record but the ones with a SID as key */
+ if (strncmp(key.dptr, "S-", 2) == 0) {
+
+ maps = talloc_realloc(NULL, *data->maps, struct id_map, num_maps+1);
+ if ( ! maps) {
+ DEBUG(0, ("Out of memory!\n"));
+ data->ret = NT_STATUS_NO_MEMORY;
+ return -1;
+ }
+ *data->maps = maps;
+ maps[num_maps].sid = talloc(maps, DOM_SID);
+ if ( ! maps[num_maps].sid) {
+ DEBUG(0, ("Out of memory!\n"));
+ data->ret = NT_STATUS_NO_MEMORY;
+ return -1;
+ }
+
+ if (!string_to_sid(maps[num_maps].sid, key.dptr)) {
+ DEBUG(10,("INVALID record %s\n", key.dptr));
+ /* continue even with errors */
+ return 0;
+ }
+
+ /* Try a UID record. */
+ if (sscanf(value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) {
+ maps[num_maps].xid.type = ID_TYPE_UID;
+ maps[num_maps].status = ID_MAPPED;
+ *data->num_maps = num_maps + 1;
+
+ /* Try a GID record. */
+ } else
+ if (sscanf(value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) {
+ maps[num_maps].xid.type = ID_TYPE_GID;
+ maps[num_maps].status = ID_MAPPED;
+ *data->num_maps = num_maps + 1;
+
+ /* Unknown record type ! */
+ } else {
+ maps[num_maps].status = ID_UNKNOWN;
+ DEBUG(2, ("Found INVALID record %s -> %s\n", key.dptr, value.dptr));
+ /* do not increment num_maps */
+ }
+ }
+
+ return 0;
+}
+
+/**********************************
+ Dump all mappings out
+**********************************/
+
+static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
+{
+ struct idmap_tdb_context *ctx;
+ struct dump_data *data;
+ NTSTATUS ret = NT_STATUS_OK;
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
+
+ data = talloc_zero(ctx, struct dump_data);
+ if ( ! data) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ data->maps = maps;
+ data->num_maps = num_maps;
+ data->ret = NT_STATUS_OK;
+
+ tdb_traverse(ctx->tdb, idmap_tdb_dump_one_entry, data);
+
+ if ( ! NT_STATUS_IS_OK(data->ret)) {
+ ret = data->ret;
+ }
+
+ talloc_free(data);
+ return ret;
+}
+
+static struct idmap_methods db_methods = {
+
+ .init = idmap_tdb_db_init,
+ .unixids_to_sids = idmap_tdb_unixids_to_sids,
+ .sids_to_unixids = idmap_tdb_sids_to_unixids,
+ .set_mapping = idmap_tdb_set_mapping,
+ .remove_mapping = idmap_tdb_remove_mapping,
+ .dump_data = idmap_tdb_dump_data,
+ .close_fn = idmap_tdb_close
+};
+
+static struct idmap_alloc_methods db_alloc_methods = {
+
+ .init = idmap_tdb_alloc_init,
+ .allocate_id = idmap_tdb_allocate_id,
+ .get_id_hwm = idmap_tdb_get_hwm,
+ .set_id_hwm = idmap_tdb_set_hwm,
+ .close_fn = idmap_tdb_alloc_close
+};
+
+NTSTATUS idmap_alloc_tdb_init(void)
+{
+ return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_alloc_methods);
+}
+
+NTSTATUS idmap_tdb_init(void)
+{
+ NTSTATUS ret;
+
+ /* FIXME: bad hack to actually register also the alloc_tdb module without changining configure.in */
+ ret = idmap_alloc_tdb_init();
+ if (! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods);
+}
diff --git a/source/nsswitch/idmap_util.c b/source/nsswitch/idmap_util.c
new file mode 100644
index 00000000000..540dafaa734
--- /dev/null
+++ b/source/nsswitch/idmap_util.c
@@ -0,0 +1,160 @@
+/*
+ Unix SMB/CIFS implementation.
+ ID Mapping
+ Copyright (C) Simo Sorce 2003
+ Copyright (C) Jeremy Allison 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/*****************************************************************
+ Returns the SID mapped to the given UID.
+ If mapping is not possible returns an error.
+*****************************************************************/
+
+NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid)
+{
+ NTSTATUS ret;
+ struct id_map map;
+ struct id_map *maps[2];
+
+ DEBUG(10,("uid = [%lu]\n", (unsigned long)uid));
+
+ map.sid = sid;
+ map.xid.type = ID_TYPE_UID;
+ map.xid.id = uid;
+
+ maps[0] = &map;
+ maps[1] = NULL;
+
+ ret = idmap_unixids_to_sids(maps);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(10, ("error mapping uid [%lu]\n", (unsigned long)uid));
+ return ret;
+ }
+
+ if (map.status != ID_MAPPED) {
+ DEBUG(10, ("uid [%lu] not mapped\n", (unsigned long)uid));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*****************************************************************
+ Returns SID mapped to the given GID.
+ If mapping is not possible returns an error.
+*****************************************************************/
+
+NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid)
+{
+ NTSTATUS ret;
+ struct id_map map;
+ struct id_map *maps[2];
+
+ DEBUG(10,("gid = [%lu]\n", (unsigned long)gid));
+
+ map.sid = sid;
+ map.xid.type = ID_TYPE_GID;
+ map.xid.id = gid;
+
+ maps[0] = &map;
+ maps[1] = NULL;
+
+ ret = idmap_unixids_to_sids(maps);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(10, ("error mapping gid [%lu]\n", (unsigned long)gid));
+ return ret;
+ }
+
+ if (map.status != ID_MAPPED) {
+ DEBUG(10, ("gid [%lu] not mapped\n", (unsigned long)gid));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*****************************************************************
+ Returns the UID mapped to the given SID.
+ If mapping is not possible or SID maps to a GID returns an error.
+*****************************************************************/
+
+NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid)
+{
+ NTSTATUS ret;
+ struct id_map map;
+ struct id_map *maps[2];
+
+ DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
+
+ map.sid = sid;
+
+ maps[0] = &map;
+ maps[1] = NULL;
+
+ ret = idmap_sids_to_unixids(maps);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(10, ("error mapping sid [%s] to uid\n", sid_string_static(sid)));
+ return ret;
+ }
+
+ if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_UID)) {
+ DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n", sid_string_static(sid), map.status, map.xid.type, map.xid.id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ *uid = map.xid.id;
+
+ return NT_STATUS_OK;
+}
+
+/*****************************************************************
+ Returns the GID mapped to the given SID.
+ If mapping is not possible or SID maps to a UID returns an error.
+*****************************************************************/
+
+NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid)
+{
+ NTSTATUS ret;
+ struct id_map map;
+ struct id_map *maps[2];
+
+ DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
+
+ map.sid = sid;
+
+ maps[0] = &map;
+ maps[1] = NULL;
+
+ ret = idmap_sids_to_unixids(maps);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(10, ("error mapping sid [%s] to gid\n", sid_string_static(sid)));
+ return ret;
+ }
+
+ if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) {
+ DEBUG(10, ("sid [%s] not mapped to an gid [%u,%u,%u]\n", sid_string_static(sid), map.status, map.xid.type, map.xid.id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ *gid = map.xid.id;
+
+ return NT_STATUS_OK;
+}
diff --git a/source/nsswitch/nss_info.c b/source/nsswitch/nss_info.c
new file mode 100644
index 00000000000..0b0caeee022
--- /dev/null
+++ b/source/nsswitch/nss_info.c
@@ -0,0 +1,266 @@
+/*
+ Unix SMB/CIFS implementation.
+ Idmap NSS headers
+
+ Copyright (C) Gerald Carter 2006
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "includes.h"
+#include "nss_info.h"
+
+static struct nss_function_entry *backends = NULL;
+static struct nss_domain_entry *nss_domain_list = NULL;
+
+/**********************************************************************
+ Get idmap nss methods.
+**********************************************************************/
+
+static struct nss_function_entry *nss_get_backend(const char *name )
+{
+ struct nss_function_entry *entry = backends;
+
+ for(entry = backends; entry; entry = entry->next) {
+ if ( strequal(entry->name, name) )
+ return entry;
+ }
+
+ return NULL;
+}
+
+/*********************************************************************
+ Allow a module to register itself as a backend.
+**********************************************************************/
+
+ NTSTATUS smb_register_idmap_nss(int version, const char *name, struct nss_info_methods *methods)
+{
+ struct nss_function_entry *entry;
+
+ if ((version != SMB_NSS_INFO_INTERFACE_VERSION)) {
+ DEBUG(0, ("smb_register_idmap_nss: Failed to register idmap_nss module.\n"
+ "The module was compiled against SMB_NSS_INFO_INTERFACE_VERSION %d,\n"
+ "current SMB_NSS_INFO_INTERFACE_VERSION is %d.\n"
+ "Please recompile against the current version of samba!\n",
+ version, SMB_NSS_INFO_INTERFACE_VERSION));
+ return NT_STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ if (!name || !name[0] || !methods) {
+ DEBUG(0,("smb_register_idmap_nss: called with NULL pointer or empty name!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ( nss_get_backend(name) ) {
+ DEBUG(0,("smb_register_idmap_nss: idmap module %s "
+ "already registered!\n", name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ entry = SMB_XMALLOC_P(struct nss_function_entry);
+ entry->name = smb_xstrdup(name);
+ entry->methods = methods;
+
+ DLIST_ADD(backends, entry);
+ DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap "
+ "nss backend '%s'\n", name));
+
+ return NT_STATUS_OK;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static BOOL parse_nss_parm( const char *config, char **backend, char **domain )
+{
+ char *p;
+ char *q;
+ int len;
+
+ *backend = *domain = NULL;
+
+ if ( !config )
+ return False;
+
+ p = strchr( config, ':' );
+
+ /* if no : then the string must be the backend name only */
+
+ if ( !p ) {
+ *backend = SMB_STRDUP( config );
+ return (*backend != NULL);
+ }
+
+ /* split the string and return the two parts */
+
+ if ( strlen(p+1) > 0 ) {
+ *domain = SMB_STRDUP( p+1 );
+ }
+
+ len = PTR_DIFF(p,config)+1;
+ if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) {
+ SAFE_FREE( *backend );
+ return False;
+ }
+
+ StrnCpy( q, config, len-1);
+ q[len-1] = '\0';
+ *backend = q;
+
+ return True;
+}
+
+/********************************************************************
+ Each nss backend must not store global state, but rather be able
+ to initialize the state on a per domain basis.
+ *******************************************************************/
+
+ NTSTATUS nss_init( const char **nss_list )
+{
+ NTSTATUS status;
+ int i;
+ char *backend, *domain;
+ struct nss_function_entry *nss_backend;
+ struct nss_domain_entry *nss_domain;
+
+ /* The "template" backend should alqays be registered as it
+ is a static module */
+
+ if ( (nss_backend = nss_get_backend( "template" )) == NULL ) {
+ static_init_nss_info;
+ }
+
+ /* Create the list of nss_domains (loading any shared plugins
+ as necessary) */
+
+ for ( i=0; nss_list && nss_list[i]; i++ ) {
+
+ if ( !parse_nss_parm(nss_list[i], &backend, &domain) ) {
+ DEBUG(0,("nss_init: failed to parse \"%s\"!\n",
+ nss_list[0]));
+ continue;
+ }
+
+ /* validate the backend */
+
+ if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
+ /* attempt to register the backend */
+ status = smb_probe_module( "nss_info", backend );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ continue;
+ }
+
+ /* try again */
+ if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
+ DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n",
+ backend));
+ continue;
+ }
+
+ }
+
+ /* fill in the nss_domain_entry and add it to the
+ list of domains */
+
+ nss_domain = TALLOC_ZERO_P( nss_domain_list, struct nss_domain_entry );
+ if ( !nss_domain ) {
+ DEBUG(0,("nss_init: talloc() failure!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nss_domain->backend = nss_backend;
+ nss_domain->domain = talloc_strdup( nss_domain, domain );
+
+ status = nss_domain->backend->methods->init( nss_domain );
+ if ( NT_STATUS_IS_OK( status ) ) {
+ DLIST_ADD( nss_domain_list, nss_domain );
+ } else {
+ DEBUG(0,("nss_init: Failed to init backend for %s domain!\n",
+ nss_domain->domain));
+ }
+
+ /* cleanup */
+
+ SAFE_FREE( backend );
+ SAFE_FREE( domain );
+ }
+
+ if ( !nss_domain_list ) {
+ DEBUG(3,("nss_init: no nss backends configured. "
+ "Defaulting to \"template\".\n"));
+
+
+ /* we shouild default to use template here */
+ }
+
+
+ return NT_STATUS_OK;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+ NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid,
+ TALLOC_CTX *ctx,
+ ADS_STRUCT *ads, LDAPMessage *msg,
+ char **homedir, char **shell, char **gecos,
+ gid_t *p_gid)
+{
+ struct nss_domain_entry *p;
+ struct nss_info_methods *m;
+
+ for ( p=nss_domain_list; p; p=p->next ) {
+ if ( strequal( p->domain, domain ) )
+ break;
+ }
+
+ /* If we didn't find a match, then use the default nss info */
+
+ if ( !p ) {
+ if ( !nss_domain_list ) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ p = nss_domain_list;
+ }
+
+ m = p->backend->methods;
+
+ return m->get_nss_info( p, user_sid, ctx, ads, msg,
+ homedir, shell, gecos, p_gid );
+}
+
+/********************************************************************
+ *******************************************************************/
+
+ NTSTATUS nss_close( const char *parameters )
+{
+ struct nss_domain_entry *p = nss_domain_list;
+ struct nss_domain_entry *q;
+
+ while ( p && p->backend && p->backend->methods ) {
+ /* close the backend */
+ p->backend->methods->close_fn();
+
+ /* free the memory */
+ q = p;
+ p = p->next;
+ TALLOC_FREE( q );
+ }
+
+ return NT_STATUS_OK;
+}
+
diff --git a/source/nsswitch/nss_info_template.c b/source/nsswitch/nss_info_template.c
new file mode 100644
index 00000000000..2a144288021
--- /dev/null
+++ b/source/nsswitch/nss_info_template.c
@@ -0,0 +1,85 @@
+/*
+ Unix SMB/CIFS implementation.
+ idMap nss template plugin
+
+ Copyright (C) Gerald Carter 2006
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "includes.h"
+#include "nss_info.h"
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS nss_template_init( struct nss_domain_entry *e )
+{
+ return NT_STATUS_OK;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS nss_template_get_info( struct nss_domain_entry *e,
+ const DOM_SID *sid,
+ TALLOC_CTX *ctx,
+ ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ char **homedir,
+ char **shell,
+ char **gecos,
+ uint32 *gid )
+{
+ if ( !homedir || !shell || !gecos )
+ return NT_STATUS_INVALID_PARAMETER;
+
+ *homedir = talloc_strdup( ctx, lp_template_homedir() );
+ *shell = talloc_strdup( ctx, lp_template_shell() );
+ *gecos = NULL;
+
+ if ( !*homedir || !*shell ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/************************************************************************
+ ***********************************************************************/
+
+static NTSTATUS nss_template_close( void )
+{
+ return NT_STATUS_OK;
+}
+
+
+/************************************************************************
+ ***********************************************************************/
+
+static struct nss_info_methods nss_template_methods = {
+ .init = nss_template_init,
+ .get_nss_info = nss_template_get_info,
+ .close_fn = nss_template_close
+};
+
+NTSTATUS nss_info_template_init( void )
+{
+ return smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
+ "template",
+ &nss_template_methods);
+}
+
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 069d15d6464..ac87fcf32ee 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -3,7 +3,7 @@
Copyright Andrew Tridgell <tridge@samba.org> 2000
Copyright Tim Potter <tpot@samba.org> 2000
Copyright Andrew Bartlett <abartlet@samba.org> 2002
- Copyright Guenther Deschner <gd@samba.org> 2005-2006
+ Copyright Guenther Deschner <gd@samba.org> 2005-2007
largely based on pam_userdb by Cristian Gafton <gafton@redhat.com>
also contains large slabs of code from pam_unix by Elliot Lee <sopwith@redhat.com>
@@ -12,46 +12,206 @@
#include "pam_winbind.h"
+#define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \
+ do { \
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] ENTER: " function " (flags: 0x%04x)", (uint32) pamh, flags); \
+ _pam_log_state(pamh, ctrl); \
+ } while (0)
+
+#define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \
+ do { \
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] LEAVE: " function " returning %d", (uint32) pamh, retval); \
+ _pam_log_state(pamh, ctrl); \
+ } while (0)
+
/* data tokens */
#define MAX_PASSWD_TRIES 3
+/*
+ * Work around the pam API that has functions with void ** as parameters.
+ * These lead to strict aliasing warnings with gcc.
+ */
+static int _pam_get_item(const pam_handle_t *pamh, int item_type,
+ const void *_item)
+{
+ const void **item = (const void **)_item;
+ return pam_get_item(pamh, item_type, item);
+}
+static int _pam_get_data(const pam_handle_t *pamh,
+ const char *module_data_name, const void *_data)
+{
+ const void **data = (const void **)_data;
+ return pam_get_data(pamh, module_data_name, data);
+}
+
/* some syslogging */
-static void _pam_log(int err, const char *format, ...)
+
+#ifdef HAVE_PAM_VSYSLOG
+static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args)
+{
+ pam_vsyslog(pamh, err, format, args);
+}
+#else
+static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args)
+{
+ char *format2 = NULL;
+ const char *service;
+
+ _pam_get_item(pamh, PAM_SERVICE, &service);
+
+ format2 = malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5);
+ if (format2 == NULL) {
+ /* what else todo ? */
+ vsyslog(err, format, args);
+ return;
+ }
+
+ sprintf(format2, "%s(%s): %s", MODULE_NAME, service, format);
+ vsyslog(err, format2, args);
+ SAFE_FREE(format2);
+}
+#endif /* HAVE_PAM_VSYSLOG */
+
+static BOOL _pam_log_is_silent(int ctrl)
+{
+ return on(ctrl, WINBIND_SILENT);
+}
+
+static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5);
+static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...)
{
va_list args;
+ if (_pam_log_is_silent(ctrl)) {
+ return;
+ }
+
va_start(args, format);
- openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
- vsyslog(err, format, args);
+ _pam_log_int(pamh, err, format, args);
va_end(args);
- closelog();
}
-static void _pam_log_debug(int ctrl, int err, const char *format, ...)
+static BOOL _pam_log_is_debug_enabled(int ctrl)
{
- va_list args;
+ if (ctrl == -1) {
+ return False;
+ }
+
+ if (_pam_log_is_silent(ctrl)) {
+ return False;
+ }
if (!(ctrl & WINBIND_DEBUG_ARG)) {
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL _pam_log_is_debug_state_enabled(int ctrl)
+{
+ if (!(ctrl & WINBIND_DEBUG_STATE)) {
+ return False;
+ }
+
+ return _pam_log_is_debug_enabled(ctrl);
+}
+
+static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5);
+static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...)
+{
+ va_list args;
+
+ if (!_pam_log_is_debug_enabled(ctrl)) {
return;
}
va_start(args, format);
- openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
- vsyslog(err, format, args);
+ _pam_log_int(pamh, err, format, args);
va_end(args);
- closelog();
}
-static int _pam_parse(int argc, const char **argv, dictionary **d)
+static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_type, const char *key, int is_string)
+{
+ const void *data = NULL;
+ if (item_type != 0) {
+ pam_get_item(pamh, item_type, &data);
+ } else {
+ pam_get_data(pamh, key, &data);
+ }
+ if (data != NULL) {
+ const char *type = (item_type != 0) ? "ITEM" : "DATA";
+ if (is_string != 0) {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = \"%s\" (0x%08x)", (uint32) pamh, type, key, (const char *) data, (uint32) data);
+ } else {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = 0x%08x", (uint32) pamh, type, key, (uint32) data);
+ }
+ }
+}
+
+#define _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, module_data_name) \
+ _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 0)
+
+#define _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, module_data_name) \
+ _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 1)
+
+#define _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, item_type) \
+ _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 0)
+
+#define _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, item_type) \
+ _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 1)
+
+#ifdef DEBUG_PASSWORD
+#define _LOG_PASSWORD_AS_STRING 1
+#else
+#define _LOG_PASSWORD_AS_STRING 0
+#endif
+
+#define _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, item_type) \
+ _pam_log_state_datum(pamh, ctrl, item_type, #item_type, _LOG_PASSWORD_AS_STRING)
+
+static void _pam_log_state(const pam_handle_t *pamh, int ctrl)
+{
+ if (!_pam_log_is_debug_state_enabled(ctrl)) {
+ return;
+ }
+
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_SERVICE);
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER);
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_TTY);
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RHOST);
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RUSER);
+ _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_OLDAUTHTOK);
+ _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_AUTHTOK);
+ _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER_PROMPT);
+ _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_CONV);
+#ifdef PAM_FAIL_DELAY
+ _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_FAIL_DELAY);
+#endif
+#ifdef PAM_REPOSITORY
+ _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_REPOSITORY);
+#endif
+
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_HOMEDIR);
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT);
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER);
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH);
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH);
+ _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET);
+}
+
+static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d)
{
int ctrl = 0;
const char *config_file = NULL;
int i;
const char **v;
+ dictionary *d = NULL;
- if (d == NULL) {
- goto config_from_pam;
+ if (flags & PAM_SILENT) {
+ ctrl |= WINBIND_SILENT;
}
for (i=argc,v=argv; i-- > 0; ++v) {
@@ -66,32 +226,44 @@ static int _pam_parse(int argc, const char **argv, dictionary **d)
config_file = PAM_WINBIND_CONFIG_FILE;
}
- *d = iniparser_load(CONST_DISCARD(char *, config_file));
- if (*d == NULL) {
+ d = iniparser_load(config_file);
+ if (d == NULL) {
goto config_from_pam;
}
- if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) {
+ if (iniparser_getboolean(d, "global:debug", False)) {
ctrl |= WINBIND_DEBUG_ARG;
}
- if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:cached_login"), False)) {
+ if (iniparser_getboolean(d, "global:debug_state", False)) {
+ ctrl |= WINBIND_DEBUG_STATE;
+ }
+
+ if (iniparser_getboolean(d, "global:cached_login", False)) {
ctrl |= WINBIND_CACHED_LOGIN;
}
- if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:krb5_auth"), False)) {
+ if (iniparser_getboolean(d, "global:krb5_auth", False)) {
ctrl |= WINBIND_KRB5_AUTH;
}
- if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:krb5_ccache_type")) != NULL) {
+ if (iniparser_getboolean(d, "global:silent", False)) {
+ ctrl |= WINBIND_SILENT;
+ }
+
+ if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) {
ctrl |= WINBIND_KRB5_CCACHE_TYPE;
}
-
- if ((iniparser_getstr(*d, CONST_DISCARD(char *, "global:require-membership-of")) != NULL) ||
- (iniparser_getstr(*d, CONST_DISCARD(char *, "global:require_membership_of")) != NULL)) {
+
+ if ((iniparser_getstr(d, "global:require-membership-of") != NULL) ||
+ (iniparser_getstr(d, "global:require_membership_of") != NULL)) {
ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
}
+ if (iniparser_getboolean(d, "global:try_first_pass", False)) {
+ ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
+ }
+
config_from_pam:
/* step through arguments */
for (i=argc,v=argv; i-- > 0; ++v) {
@@ -99,6 +271,8 @@ config_from_pam:
/* generic options */
if (!strcmp(*v,"debug"))
ctrl |= WINBIND_DEBUG_ARG;
+ else if (!strcasecmp(*v, "debug_state"))
+ ctrl |= WINBIND_DEBUG_STATE;
else if (!strcasecmp(*v, "use_authtok"))
ctrl |= WINBIND_USE_AUTHTOK_ARG;
else if (!strcasecmp(*v, "use_first_pass"))
@@ -118,24 +292,41 @@ config_from_pam:
else if (!strcasecmp(*v, "cached_login"))
ctrl |= WINBIND_CACHED_LOGIN;
else {
- _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *v);
+ _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v);
+ return -1;
}
}
+
+ if (result_d) {
+ *result_d = d;
+ } else {
+ if (d) {
+ iniparser_freedict(d);
+ }
+ }
+
return ctrl;
};
static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status)
{
+ int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL);
+ if (_pam_log_is_debug_state_enabled(ctrl)) {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] CLEAN: cleaning up PAM data 0x%08x (error_status = %d)", (uint32) pamh, (uint32) data, error_status);
+ }
SAFE_FREE(data);
}
+
static const struct ntstatus_errors {
const char *ntstatus_string;
const char *error_string;
} ntstatus_errors[] = {
{"NT_STATUS_OK", "Success"},
{"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"},
+ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", "No domain controllers found"},
+ {"NT_STATUS_NO_LOGON_SERVERS", "No logon servers"},
{"NT_STATUS_PWD_TOO_SHORT", "Password too short"},
{"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"},
{"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"},
@@ -175,7 +366,7 @@ static int converse(pam_handle_t *pamh, int nargs,
int retval;
struct pam_conv *conv;
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv );
+ retval = _pam_get_item(pamh, PAM_CONV, &conv );
if (retval == PAM_SUCCESS) {
retval = conv->conv(nargs, (const struct pam_message **)message,
response, conv->appdata_ptr);
@@ -185,13 +376,17 @@ static int converse(pam_handle_t *pamh, int nargs,
}
-static int _make_remark(pam_handle_t * pamh, int type, const char *text)
+static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *text)
{
int retval = PAM_SUCCESS;
struct pam_message *pmsg[1], msg[1];
struct pam_response *resp;
+ if (flags & WINBIND_SILENT) {
+ return PAM_SUCCESS;
+ }
+
pmsg[0] = &msg[0];
msg[0].msg = CONST_DISCARD(char *, text);
msg[0].msg_style = type;
@@ -205,21 +400,34 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
return retval;
}
-static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...)
+static int _make_remark_v(pam_handle_t * pamh, int flags, int type, const char *format, va_list args)
{
- va_list args;
char *var;
int ret;
- va_start(args, format);
- vasprintf(&var, format, args);
- va_end(args);
+ ret = vasprintf(&var, format, args);
+ if (ret < 0) {
+ _pam_log(pamh, 0, LOG_ERR, "memory allocation failure");
+ return ret;
+ }
- ret = _make_remark(pamh, type, var);
+ ret = _make_remark(pamh, flags, type, var);
SAFE_FREE(var);
return ret;
}
+static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) PRINTF_ATTRIBUTE(4,5);
+static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, format);
+ ret = _make_remark_v(pamh, flags, type, format, args);
+ va_end(args);
+ return ret;
+}
+
static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
enum winbindd_cmd req_type,
struct winbindd_request *request,
@@ -229,14 +437,14 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
init_request(request, req_type);
if (write_sock(request, sizeof(*request), 0) == -1) {
- _pam_log(LOG_ERR, "write to socket failed!");
+ _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!");
close_sock();
return PAM_SERVICE_ERR;
}
/* Wait for reply */
if (read_reply(response) == -1) {
- _pam_log(LOG_ERR, "read from socket failed!");
+ _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!");
close_sock();
return PAM_SERVICE_ERR;
}
@@ -245,24 +453,41 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
close_sock();
/* Copy reply data from socket */
- if (response->result != WINBINDD_OK) {
- if (response->data.auth.pam_error != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s",
- response->data.auth.error_string,
- pam_strerror(pamh, response->data.auth.pam_error),
- response->data.auth.pam_error,
- response->data.auth.nt_status_string);
- return response->data.auth.pam_error;
- } else {
- _pam_log(LOG_ERR, "request failed, but PAM error 0!");
- return PAM_SERVICE_ERR;
- }
+ if (response->result == WINBINDD_OK) {
+ return PAM_SUCCESS;
}
- return PAM_SUCCESS;
+ /* no need to check for pam_error codes for getpwnam() */
+ switch (req_type) {
+
+ case WINBINDD_GETPWNAM:
+ case WINBINDD_LOOKUPNAME:
+ if (strlen(response->data.auth.nt_status_string) > 0) {
+ _pam_log(pamh, ctrl, LOG_ERR, "request failed, NT error was %s",
+ response->data.auth.nt_status_string);
+ } else {
+ _pam_log(pamh, ctrl, LOG_ERR, "request failed");
+ }
+ return PAM_USER_UNKNOWN;
+ default:
+ break;
+ }
+
+ if (response->data.auth.pam_error != PAM_SUCCESS) {
+ _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s",
+ response->data.auth.error_string,
+ pam_strerror(pamh, response->data.auth.pam_error),
+ response->data.auth.pam_error,
+ response->data.auth.nt_status_string);
+ return response->data.auth.pam_error;
+ }
+
+ _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!");
+
+ return PAM_SERVICE_ERR;
}
-static int pam_winbind_request_log(pam_handle_t * pamh,
+static int pam_winbind_request_log(pam_handle_t * pamh,
int ctrl,
enum winbindd_cmd req_type,
struct winbindd_request *request,
@@ -276,61 +501,516 @@ static int pam_winbind_request_log(pam_handle_t * pamh,
switch (retval) {
case PAM_AUTH_ERR:
/* incorrect password */
- _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user);
+ _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access (incorrect password or invalid membership)", user);
return retval;
case PAM_ACCT_EXPIRED:
/* account expired */
- _pam_log(LOG_WARNING, "user `%s' account expired", user);
+ _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", user);
return retval;
case PAM_AUTHTOK_EXPIRED:
/* password expired */
- _pam_log(LOG_WARNING, "user `%s' password expired", user);
+ _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", user);
return retval;
case PAM_NEW_AUTHTOK_REQD:
/* new password required */
- _pam_log(LOG_WARNING, "user `%s' new password required", user);
+ _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password required", user);
return retval;
case PAM_USER_UNKNOWN:
/* the user does not exist */
- _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", user);
+ _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", user);
if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
return PAM_IGNORE;
}
return retval;
case PAM_SUCCESS:
- if (req_type == WINBINDD_PAM_AUTH) {
- /* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted access", user);
- } else if (req_type == WINBINDD_PAM_CHAUTHTOK) {
- /* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' password changed", user);
- } else {
- /* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' OK", user);
+ /* Otherwise, the authentication looked good */
+ switch (req_type) {
+ case WINBINDD_INFO:
+ break;
+ case WINBINDD_PAM_AUTH:
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user);
+ break;
+ case WINBINDD_PAM_CHAUTHTOK:
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user);
+ break;
+ default:
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user);
+ break;
}
return retval;
default:
/* we don't know anything about this return value */
- _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')",
+ _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')",
retval, user);
return retval;
}
}
+/**
+ * send a password expiry message if required
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param next_change expected (calculated) next expiry date.
+ * @param already_expired pointer to a boolean to indicate if the password is
+ * already expired.
+ *
+ * @return boolean Returns True if message has been sent, False if not.
+ */
+
+static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now, BOOL *already_expired)
+{
+ int days = 0;
+ struct tm tm_now, tm_next_change;
+
+ if (already_expired) {
+ *already_expired = False;
+ }
+
+ if (next_change <= now) {
+ PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED");
+ if (already_expired) {
+ *already_expired = True;
+ }
+ return True;
+ }
+
+ if ((next_change < 0) ||
+ (next_change > now + DAYS_TO_WARN_BEFORE_PWD_EXPIRES * SECONDS_PER_DAY)) {
+ return False;
+ }
+
+ if ((localtime_r(&now, &tm_now) == NULL) ||
+ (localtime_r(&next_change, &tm_next_change) == NULL)) {
+ return False;
+ }
+
+ days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365);
+
+ if (days == 0) {
+ _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today");
+ return True;
+ }
+
+ if (days > 0 && days < DAYS_TO_WARN_BEFORE_PWD_EXPIRES) {
+ _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s",
+ days, (days > 1) ? "days":"day");
+ return True;
+ }
+
+ return False;
+}
+
+/**
+ * Send a warning if the password expires in the near future
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param response The full authentication response structure.
+ * @param already_expired boolean, is the pwd already expired?
+ *
+ * @return void.
+ */
+
+static void _pam_warn_password_expiry(pam_handle_t *pamh,
+ int flags,
+ const struct winbindd_response *response,
+ BOOL *already_expired)
+{
+ time_t now = time(NULL);
+ time_t next_change = 0;
+
+ if (already_expired) {
+ *already_expired = False;
+ }
+
+ /* accounts with ACB_PWNOEXP set never receive a warning */
+ if (response->data.auth.info3.acct_flags & ACB_PWNOEXP) {
+ return;
+ }
+
+ /* no point in sending a warning if this is a grace logon */
+ if (PAM_WB_GRACE_LOGON(response->data.auth.info3.user_flgs)) {
+ return;
+ }
+
+ /* check if the info3 must change timestamp has been set */
+ next_change = response->data.auth.info3.pass_must_change_time;
+
+ if (_pam_send_password_expiry_message(pamh, flags, next_change, now,
+ already_expired)) {
+ return;
+ }
+
+ /* now check for the global password policy */
+ /* good catch from Ralf Haferkamp: an expiry of "never" is translated
+ * to -1 */
+ if (response->data.auth.policy.expire <= 0) {
+ return;
+ }
+
+ next_change = response->data.auth.info3.pass_last_set_time +
+ response->data.auth.policy.expire;
+
+ if (_pam_send_password_expiry_message(pamh, flags, next_change, now,
+ already_expired)) {
+ return;
+ }
+
+ /* no warning sent */
+}
+
+#define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0)
+
+static BOOL safe_append_string(char *dest,
+ const char *src,
+ int dest_buffer_size)
+/**
+ * Append a string, making sure not to overflow and to always return a NULL-terminated
+ * string.
+ *
+ * @param dest Destination string buffer (must already be NULL-terminated).
+ * @param src Source string buffer.
+ * @param dest_buffer_size Size of dest buffer in bytes.
+ *
+ * @return False if dest buffer is not big enough (no bytes copied), True on success.
+ */
+{
+ int dest_length = strlen(dest);
+ int src_length = strlen(src);
+
+ if ( dest_length + src_length + 1 > dest_buffer_size ) {
+ return False;
+ }
+
+ memcpy(dest + dest_length, src, src_length + 1);
+ return True;
+}
+
+static BOOL winbind_name_to_sid_string(pam_handle_t *pamh,
+ int ctrl,
+ const char *user,
+ const char *name,
+ char *sid_list_buffer,
+ int sid_list_buffer_size)
+/**
+ * Convert a names into a SID string, appending it to a buffer.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param user User in PAM request.
+ * @param name Name to convert.
+ * @param sid_list_buffer Where to append the string sid.
+ * @param sid_list_buffer Size of sid_list_buffer (in bytes).
+ *
+ * @return False on failure, True on success.
+ */
+{
+ const char* sid_string;
+ struct winbindd_response sid_response;
+
+ /* lookup name? */
+ if (IS_SID_STRING(name)) {
+ sid_string = name;
+ } else {
+ struct winbindd_request sid_request;
+
+ ZERO_STRUCT(sid_request);
+ ZERO_STRUCT(sid_response);
+
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", name);
+
+ /* fortunatly winbindd can handle non-separated names */
+ strncpy(sid_request.data.name.name, name,
+ sizeof(sid_request.data.name.name) - 1);
+
+ if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) {
+ _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name);
+ return False;
+ }
+
+ sid_string = sid_response.data.sid.sid;
+ }
+
+ if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) {
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL winbind_name_list_to_sid_string_list(pam_handle_t *pamh,
+ int ctrl,
+ const char *user,
+ const char *name_list,
+ char *sid_list_buffer,
+ int sid_list_buffer_size)
+/**
+ * Convert a list of names into a list of sids.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param user User in PAM request.
+ * @param name_list List of names or string sids, separated by commas.
+ * @param sid_list_buffer Where to put the list of string sids.
+ * @param sid_list_buffer Size of sid_list_buffer (in bytes).
+ *
+ * @return False on failure, True on success.
+ */
+{
+ BOOL result = False;
+ char *current_name = NULL;
+ const char *search_location;
+ const char *comma;
+
+ if ( sid_list_buffer_size > 0 ) {
+ sid_list_buffer[0] = 0;
+ }
+
+ search_location = name_list;
+ while ( (comma = strstr(search_location, ",")) != NULL ) {
+ current_name = strndup(search_location, comma - search_location);
+ if (NULL == current_name) {
+ goto out;
+ }
+
+ if (!winbind_name_to_sid_string(pamh, ctrl, user, current_name, sid_list_buffer, sid_list_buffer_size)) {
+ goto out;
+ }
+
+ SAFE_FREE(current_name);
+
+ if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) {
+ goto out;
+ }
+
+ search_location = comma + 1;
+ }
+
+ if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, sid_list_buffer, sid_list_buffer_size)) {
+ goto out;
+ }
+
+ result = True;
+
+out:
+ SAFE_FREE(current_name);
+ return result;
+}
+
+/**
+ * put krb5ccname variable into environment
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param krb5ccname env variable retrieved from winbindd.
+ *
+ * @return void.
+ */
+
+static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5ccname)
+{
+ char var[PATH_MAX];
+ int ret;
+
+ if (off(ctrl, WINBIND_KRB5_AUTH)) {
+ return;
+ }
+
+ if (!krb5ccname || (strlen(krb5ccname) == 0)) {
+ return;
+ }
+
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname);
+
+ if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) {
+ return;
+ }
+
+ ret = pam_putenv(pamh, var);
+ if (ret) {
+ _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s: %s",
+ var, pam_strerror(pamh, ret));
+ }
+}
+
+/**
+ * Set string into the PAM stack.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param data_name Key name for pam_set_data.
+ * @param value String value.
+ *
+ * @return void.
+ */
+
+static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_name, const char *value)
+{
+ int ret;
+
+ if ( !data_name || !value || (strlen(data_name) == 0) || (strlen(value) == 0) ) {
+ return;
+ }
+
+ ret = pam_set_data(pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func);
+ if (ret) {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data %s: %s\n",
+ data_name, pam_strerror(pamh, ret));
+ }
+
+}
+
+/**
+ * Set info3 strings into the PAM stack.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param data_name Key name for pam_set_data.
+ * @param value String value.
+ *
+ * @return void.
+ */
+
+static void _pam_set_data_info3(pam_handle_t *pamh, int ctrl, struct winbindd_response *response)
+{
+ _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir);
+ _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script);
+ _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv);
+ _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path);
+}
+
+/**
+ * Free info3 strings in the PAM stack.
+ *
+ * @param pamh PAM handle
+ *
+ * @return void.
+ */
+
+static void _pam_free_data_info3(pam_handle_t *pamh)
+{
+ pam_set_data(pamh, PAM_WINBIND_HOMEDIR, NULL, NULL);
+ pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, NULL, NULL);
+ pam_set_data(pamh, PAM_WINBIND_LOGONSERVER, NULL, NULL);
+ pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL);
+}
+
+/**
+ * Send PAM_ERROR_MSG for cached or grace logons.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param username User in PAM request.
+ * @param info3_user_flgs Info3 flags containing logon type bits.
+ *
+ * @return void.
+ */
+
+static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs)
+{
+ /* inform about logon type */
+ if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
+
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG,
+ "Grace login. Please change your password as soon you're online again");
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG,
+ "User %s logged on using grace logon\n", username);
+
+ } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
+
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG,
+ "Logging on using cached account. Network resources can be unavailable");
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG,
+ "User %s logged on using cached account\n", username);
+ }
+}
+
+/**
+ * Compose Password Restriction String for a PAM_ERROR_MSG conversation.
+ *
+ * @param response The struct winbindd_response.
+ *
+ * @return string (caller needs to free).
+ */
+
+static char *_pam_compose_pwd_restriction_string(struct winbindd_response *response)
+{
+ char *str = NULL;
+ size_t offset = 0, ret = 0, str_size = 1024;
+
+ str = (char *)malloc(str_size);
+ if (!str) {
+ return NULL;
+ }
+
+ memset(str, '\0', str_size);
+
+ offset = snprintf(str, str_size, "Your password ");
+ if (offset == -1) {
+ goto failed;
+ }
+
+ if (response->data.auth.policy.min_length_password > 0) {
+ ret = snprintf(str+offset, str_size-offset,
+ "must be at least %d characters; ",
+ response->data.auth.policy.min_length_password);
+ if (ret == -1) {
+ goto failed;
+ }
+ offset += ret;
+ }
+
+ if (response->data.auth.policy.password_history > 0) {
+ ret = snprintf(str+offset, str_size-offset,
+ "cannot repeat any of your previous %d passwords; ",
+ response->data.auth.policy.password_history);
+ if (ret == -1) {
+ goto failed;
+ }
+ offset += ret;
+ }
+
+ if (response->data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) {
+ ret = snprintf(str+offset, str_size-offset,
+ "must contain capitals, numerals or punctuation; "
+ "and cannot contain your account or full name; ");
+ if (ret == -1) {
+ goto failed;
+ }
+ offset += ret;
+ }
+
+ ret = snprintf(str+offset, str_size-offset,
+ "Please type a different password. "
+ "Type a password which meets these requirements in both text boxes.");
+ if (ret == -1) {
+ goto failed;
+ }
+
+ return str;
+
+ failed:
+ SAFE_FREE(str);
+ return NULL;
+}
+
/* talk to winbindd */
-static int winbind_auth_request(pam_handle_t * pamh,
+static int winbind_auth_request(pam_handle_t * pamh,
int ctrl,
const char *user,
const char *pass,
const char *member,
const char *cctype,
- int process_result,
- time_t *pwd_last_set)
+ struct winbindd_response *p_response,
+ time_t *pwd_last_set,
+ char **user_ret)
{
struct winbindd_request request;
struct winbindd_response response;
int ret;
+ BOOL already_expired = False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
@@ -350,14 +1030,9 @@ static int winbind_auth_request(pam_handle_t * pamh,
request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM;
- if (ctrl & WINBIND_KRB5_AUTH) {
-
+ if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) {
struct passwd *pwd = NULL;
- _pam_log_debug(ctrl, LOG_DEBUG, "enabling krb5 login flag\n");
-
- request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5;
-
pwd = getpwnam(user);
if (pwd == NULL) {
return PAM_USER_UNKNOWN;
@@ -365,158 +1040,101 @@ static int winbind_auth_request(pam_handle_t * pamh,
request.data.auth.uid = pwd->pw_uid;
}
+ if (ctrl & WINBIND_KRB5_AUTH) {
+
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n");
+
+ request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5;
+ }
+
if (ctrl & WINBIND_CACHED_LOGIN) {
- _pam_log_debug(ctrl, LOG_DEBUG, "enabling cached login flag\n");
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n");
request.flags |= WBFLAG_PAM_CACHED_LOGIN;
}
+ if (user_ret) {
+ *user_ret = NULL;
+ request.flags |= WBFLAG_PAM_UNIX_NAME;
+ }
+
if (cctype != NULL) {
strncpy(request.data.auth.krb5_cc_type, cctype,
sizeof(request.data.auth.krb5_cc_type) - 1);
- _pam_log_debug(ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype);
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype);
}
request.data.auth.require_membership_of_sid[0] = '\0';
if (member != NULL) {
- strncpy(request.data.auth.require_membership_of_sid, member,
- sizeof(request.data.auth.require_membership_of_sid)-1);
- }
- /* lookup name? */
- if ( (member != NULL) && (strncmp("S-", member, 2) != 0) ) {
-
- struct winbindd_request sid_request;
- struct winbindd_response sid_response;
-
- ZERO_STRUCT(sid_request);
- ZERO_STRUCT(sid_response);
+ if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, member,
+ request.data.auth.require_membership_of_sid,
+ sizeof(request.data.auth.require_membership_of_sid))) {
- _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member);
-
- /* fortunatly winbindd can handle non-separated names */
- strncpy(sid_request.data.name.name, member,
- sizeof(sid_request.data.name.name) - 1);
-
- if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) {
- _pam_log(LOG_INFO, "could not lookup name: %s\n", member);
+ _pam_log_debug(pamh, ctrl, LOG_ERR, "failed to serialize membership of sid \"%s\"\n", member);
return PAM_AUTH_ERR;
}
-
- member = sid_response.data.sid.sid;
-
- strncpy(request.data.auth.require_membership_of_sid, member,
- sizeof(request.data.auth.require_membership_of_sid)-1);
}
-
+
ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user);
if (pwd_last_set) {
*pwd_last_set = response.data.auth.info3.pass_last_set_time;
}
- if ((ctrl & WINBIND_KRB5_AUTH) &&
- response.data.auth.krb5ccname[0] != '\0') {
-
- char var[PATH_MAX];
-
- _pam_log_debug(ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s",
- response.data.auth.krb5ccname);
-
- snprintf(var, sizeof(var), "KRB5CCNAME=%s", response.data.auth.krb5ccname);
-
- ret = pam_putenv(pamh, var);
- if (ret != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "failed to set KRB5CCNAME to %s", var);
- return ret;
- }
- }
-
- if (!process_result) {
+ if (p_response) {
+ /* We want to process the response in the caller. */
+ *p_response = response;
return ret;
}
if (ret) {
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_EXPIRED");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_MUST_CHANGE");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_WORKSTATION");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_LOGON_HOURS");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_EXPIRED");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_DISABLED");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_LOCKED_OUT");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT");
- }
-
- /* handle the case where the auth was ok, but the password must expire right now */
- /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */
- if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) &&
- (response.data.auth.policy.expire > 0) &&
- (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) {
-
- ret = PAM_AUTHTOK_EXPIRED;
-
- _pam_log_debug(ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, "
- "the policy says it should expire here %d (now it's: %d)\n",
- response.data.auth.info3.pass_last_set_time,
- response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire,
- time(NULL));
-
- PAM_WB_REMARK_DIRECT_RET(pamh, "NT_STATUS_PASSWORD_EXPIRED");
-
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_EXPIRED");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_MUST_CHANGE");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_WORKSTATION");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_LOGON_HOURS");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_EXPIRED");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_DISABLED");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_LOCKED_OUT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_WRONG_PASSWORD");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED");
}
- /* warn a user if the password is about to expire soon */
- if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) &&
- (response.data.auth.policy.expire) &&
- (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) {
-
- int days = response.data.auth.policy.expire / SECONDS_PER_DAY;
- if (days <= DAYS_TO_WARN_BEFORE_PWD_EXPIRES) {
- _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d days", days);
- }
- }
+ if (ret == PAM_SUCCESS) {
- if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
- _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable");
- _pam_log_debug(ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user);
- }
+ /* warn a user if the password is about to expire soon */
+ _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired);
- /* save the CIFS homedir for pam_cifs / pam_mount */
- if (response.data.auth.info3.home_dir[0] != '\0') {
+ if (already_expired == True) {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired "
+ "(Password was last set: %lld, the policy says "
+ "it should expire here %lld (now it's: %lu))\n",
+ response.data.auth.info3.pass_last_set_time,
+ response.data.auth.info3.pass_last_set_time +
+ response.data.auth.policy.expire,
+ time(NULL));
- int ret2 = pam_set_data(pamh, PAM_WINBIND_HOMEDIR,
- (void *) strdup(response.data.auth.info3.home_dir),
- _pam_winbind_cleanup_func);
- if (ret2) {
- _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s",
- pam_strerror(pamh, ret2));
+ return PAM_AUTHTOK_EXPIRED;
}
- }
+ /* inform about logon type */
+ _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs);
- /* save the logon script path for other PAM modules */
- if (response.data.auth.info3.logon_script[0] != '\0') {
+ /* set some info3 info for other modules in the stack */
+ _pam_set_data_info3(pamh, ctrl, &response);
- int ret2 = pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT,
- (void *) strdup(response.data.auth.info3.logon_script),
- _pam_winbind_cleanup_func);
- if (ret2) {
- _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s",
- pam_strerror(pamh, ret2));
- }
- }
+ /* put krb5ccname into env */
+ _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname);
- /* save the profile path for other PAM modules */
- if (response.data.auth.info3.profile_path[0] != '\0') {
-
- int ret2 = pam_set_data(pamh, PAM_WINBIND_PROFILEPATH,
- (void *) strdup(response.data.auth.info3.profile_path),
- _pam_winbind_cleanup_func);
- if (ret2) {
- _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s",
- pam_strerror(pamh, ret2));
+ /* If winbindd returned a username, return the pointer to it here. */
+ if (user_ret && response.extra_data.data) {
+ /* We have to trust it's a null terminated string. */
+ *user_ret = (char *)response.extra_data.data;
}
}
@@ -567,20 +1185,24 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
return ret;
}
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_BACKUP_CONTROLLER");
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCESS_DENIED");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_BACKUP_CONTROLLER");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED");
/* TODO: tell the min pwd length ? */
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_SHORT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_SHORT");
/* TODO: tell the minage ? */
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_RECENT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_RECENT");
/* TODO: tell the history length ? */
- PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT");
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_HISTORY_CONFLICT");
if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) {
+ char *pwd_restriction_string = NULL;
+
/* FIXME: avoid to send multiple PAM messages after another */
switch (response.data.auth.reject_reason) {
case -1:
@@ -588,37 +1210,30 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
case REJECT_REASON_OTHER:
if ((response.data.auth.policy.min_passwordage > 0) &&
(pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) {
- PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT");
+ PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT");
}
break;
case REJECT_REASON_TOO_SHORT:
- PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT");
+ PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT");
break;
case REJECT_REASON_IN_HISTORY:
- PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_HISTORY_CONFLICT");
+ PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT");
break;
case REJECT_REASON_NOT_COMPLEX:
- _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements");
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet complexity requirements");
break;
default:
- _pam_log_debug(ctrl, LOG_DEBUG,
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG,
"unknown password change reject reason: %d",
response.data.auth.reject_reason);
break;
}
- _make_remark_format(pamh, PAM_ERROR_MSG,
- "Your password must be at least %d characters; "
- "cannot repeat any of the your previous %d passwords"
- "%s. "
- "Please type a different password. "
- "Type a password which meets these requirements in both text boxes.",
- response.data.auth.policy.min_length_password,
- response.data.auth.policy.password_history,
- (response.data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) ?
- "; must contain capitals, numerals or punctuation; and cannot contain your account or full name" :
- "");
-
+ pwd_restriction_string = _pam_compose_pwd_restriction_string(&response);
+ if (pwd_restriction_string) {
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG, pwd_restriction_string);
+ SAFE_FREE(pwd_restriction_string);
+ }
}
return ret;
@@ -632,7 +1247,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
* 0 = OK
* -1 = System error
*/
-static int valid_user(const char *user, pam_handle_t *pamh, int ctrl)
+static int valid_user(pam_handle_t *pamh, int ctrl, const char *user)
{
/* check not only if the user is available over NSS calls, also make
* sure it's really a winbind user, this is important when stacking PAM
@@ -690,6 +1305,8 @@ static int _winbind_read_password(pam_handle_t * pamh,
const char *item;
char *token;
+ _pam_log(pamh, ctrl, LOG_DEBUG, "getting password (0x%08x)", ctrl);
+
/*
* make sure nothing inappropriate gets returned
*/
@@ -707,16 +1324,18 @@ static int _winbind_read_password(pam_handle_t * pamh,
*/
if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) {
- retval = pam_get_item(pamh, authtok_flag, (const void **) &item);
+ retval = _pam_get_item(pamh, authtok_flag, &item);
if (retval != PAM_SUCCESS) {
/* very strange. */
- _pam_log(LOG_ALERT,
+ _pam_log(pamh, ctrl, LOG_ALERT,
"pam_get_item returned error to unix-read-password"
);
return retval;
} else if (item != NULL) { /* we have a password! */
*pass = item;
item = NULL;
+ _pam_log(pamh, ctrl, LOG_DEBUG,
+ "pam_get_item returned a password");
return PAM_SUCCESS;
} else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) {
return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */
@@ -737,7 +1356,7 @@ static int _winbind_read_password(pam_handle_t * pamh,
/* prepare to converse */
- if (comment != NULL) {
+ if (comment != NULL && off(ctrl, WINBIND_SILENT)) {
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_TEXT_INFO;
msg[0].msg = CONST_DISCARD(char *, comment);
@@ -775,11 +1394,11 @@ static int _winbind_read_password(pam_handle_t * pamh,
|| strcmp(token, resp[i - 1].resp)) {
_pam_delete(token); /* mistyped */
retval = PAM_AUTHTOK_RECOVER_ERR;
- _make_remark(pamh, PAM_ERROR_MSG, MISTYPED_PASS);
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS);
}
}
} else {
- _pam_log(LOG_NOTICE, "could not recover authentication token");
+ _pam_log(pamh, ctrl, LOG_NOTICE, "could not recover authentication token");
retval = PAM_AUTHTOK_RECOVER_ERR;
}
@@ -798,7 +1417,7 @@ static int _winbind_read_password(pam_handle_t * pamh,
}
if (retval != PAM_SUCCESS) {
- _pam_log_debug(ctrl, LOG_DEBUG,
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG,
"unable to obtain a password");
return retval;
}
@@ -809,9 +1428,9 @@ static int _winbind_read_password(pam_handle_t * pamh,
retval = pam_set_item(pamh, authtok_flag, token);
_pam_delete(token); /* clean it up */
if (retval != PAM_SUCCESS ||
- (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) {
+ (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) {
- _pam_log(LOG_CRIT, "error manipulating password");
+ _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password");
return retval;
}
@@ -822,18 +1441,19 @@ static int _winbind_read_password(pam_handle_t * pamh,
return PAM_SUCCESS;
}
-const char *get_conf_item_string(int argc,
+const char *get_conf_item_string(const pam_handle_t *pamh,
+ int argc,
const char **argv,
int ctrl,
dictionary *d,
const char *item,
- int flag)
+ int config_flag)
{
int i = 0;
const char *parm_opt = NULL;
char *key = NULL;
- if (!(ctrl & flag)) {
+ if (!(ctrl & config_flag)) {
goto out;
}
@@ -855,34 +1475,34 @@ const char *get_conf_item_string(int argc,
char *p;
if ( (p = strchr( argv[i], '=' )) == NULL) {
- _pam_log(LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item);
+ _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item);
goto out;
}
- _pam_log_debug(ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1);
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1);
return p + 1;
}
}
if (d != NULL) {
- _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
}
out:
return parm_opt;
}
-const char *get_krb5_cc_type_from_config(int argc, const char **argv, int ctrl, dictionary *d)
+const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d)
{
- return get_conf_item_string(argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE);
+ return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE);
}
-const char *get_member_from_config(int argc, const char **argv, int ctrl, dictionary *d)
+const char *get_member_from_config(const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d)
{
const char *ret = NULL;
- ret = get_conf_item_string(argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP);
+ ret = get_conf_item_string(pamh, argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP);
if (ret) {
return ret;
}
- return get_conf_item_string(argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP);
+ return get_conf_item_string(pamh, argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP);
}
PAM_EXTERN
@@ -895,20 +1515,22 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
const char *cctype = NULL;
int retval = PAM_AUTH_ERR;
dictionary *d = NULL;
+ char *username_ret = NULL;
+ char *new_authtok_required = NULL;
/* parse arguments */
- int ctrl = _pam_parse(argc, argv, &d);
+ int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
retval = PAM_SYSTEM_ERR;
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", pamh, ctrl, flags);
/* Get the username */
retval = pam_get_user(pamh, &username, NULL);
if ((retval != PAM_SUCCESS) || (!username)) {
- _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username");
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "can not get the username");
retval = PAM_SERVICE_ERR;
goto out;
}
@@ -918,7 +1540,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
&password);
if (retval != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "Could not retrieve user's password");
+ _pam_log(pamh, ctrl, LOG_ERR, "Could not retrieve user's password");
retval = PAM_AUTHTOK_ERR;
goto out;
}
@@ -926,39 +1548,66 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
/* Let's not give too much away in the log file */
#ifdef DEBUG_PASSWORD
- _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s' with password `%s'",
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'",
username, password);
#else
- _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s'", username);
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", username);
#endif
- member = get_member_from_config(argc, argv, ctrl, d);
+ member = get_member_from_config(pamh, argc, argv, ctrl, d);
- cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d);
+ cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d);
/* Now use the username to look up password */
- retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True, NULL);
+ retval = winbind_auth_request(pamh, ctrl, username, password, member,
+ cctype, NULL, NULL, &username_ret);
if (retval == PAM_NEW_AUTHTOK_REQD ||
retval == PAM_AUTHTOK_EXPIRED) {
- char *buf;
+ char *new_authtok_required_during_auth = NULL;
- if (!asprintf(&buf, "%d", retval)) {
+ if (!asprintf(&new_authtok_required, "%d", retval)) {
retval = PAM_BUF_ERR;
goto out;
}
- pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func);
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func);
retval = PAM_SUCCESS;
+
+ if (!asprintf(&new_authtok_required_during_auth, "%d", True)) {
+ retval = PAM_BUF_ERR;
+ goto out;
+ }
+
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH,
+ new_authtok_required_during_auth, _pam_winbind_cleanup_func);
+
goto out;
}
out:
+ if (username_ret) {
+ pam_set_item (pamh, PAM_USER, username_ret);
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret);
+ free(username_ret);
+ }
+
if (d) {
iniparser_freedict(d);
}
+
+ if (!new_authtok_required) {
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL);
+ }
+
+ if (retval != PAM_SUCCESS) {
+ _pam_free_data_info3(pamh);
+ }
+
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", pamh, ctrl, retval);
+
return retval;
}
@@ -966,19 +1615,48 @@ PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
+ int ret = PAM_SYSTEM_ERR;
+ dictionary *d = NULL;
+
/* parse arguments */
- int ctrl = _pam_parse(argc, argv, NULL);
+ int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
- return PAM_SYSTEM_ERR;
+ ret = PAM_SYSTEM_ERR;
+ goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags);
+
+ switch (flags & ~PAM_SILENT) {
+
+ case PAM_DELETE_CRED:
+ ret = pam_sm_close_session(pamh, flags, argc, argv);
+ break;
+ case PAM_REFRESH_CRED:
+ _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented");
+ ret = PAM_SUCCESS;
+ break;
+ case PAM_REINITIALIZE_CRED:
+ _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented");
+ ret = PAM_SUCCESS;
+ break;
+ case PAM_ESTABLISH_CRED:
+ _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented");
+ ret = PAM_SUCCESS;
+ break;
+ default:
+ ret = PAM_SYSTEM_ERR;
+ break;
+ }
- if (flags & PAM_DELETE_CRED) {
- return pam_sm_close_session(pamh, flags, argc, argv);
+ out:
+ if (d) {
+ iniparser_freedict(d);
}
- return PAM_SUCCESS;
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret);
+
+ return ret;
}
/*
@@ -990,85 +1668,117 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
const char *username;
- int retval = PAM_USER_UNKNOWN;
+ int ret = PAM_USER_UNKNOWN;
void *tmp = NULL;
+ dictionary *d = NULL;
/* parse arguments */
- int ctrl = _pam_parse(argc, argv, NULL);
+ int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
return PAM_SYSTEM_ERR;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", pamh, ctrl, flags);
/* Get the username */
- retval = pam_get_user(pamh, &username, NULL);
- if ((retval != PAM_SUCCESS) || (!username)) {
- _pam_log_debug(ctrl, LOG_DEBUG,"can not get the username");
- return PAM_SERVICE_ERR;
+ ret = pam_get_user(pamh, &username, NULL);
+ if ((ret != PAM_SUCCESS) || (!username)) {
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username");
+ ret = PAM_SERVICE_ERR;
+ goto out;
}
/* Verify the username */
- retval = valid_user(username, pamh, ctrl);
- switch (retval) {
+ ret = valid_user(pamh, ctrl, username);
+ switch (ret) {
case -1:
/* some sort of system error. The log was already printed */
- return PAM_SERVICE_ERR;
+ ret = PAM_SERVICE_ERR;
+ goto out;
case 1:
/* the user does not exist */
- _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", username);
+ _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username);
if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
- return PAM_IGNORE;
+ ret = PAM_IGNORE;
+ goto out;
}
- return PAM_USER_UNKNOWN;
+ ret = PAM_USER_UNKNOWN;
+ goto out;
case 0:
pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp);
if (tmp != NULL) {
- retval = atoi(tmp);
- switch (retval) {
+ ret = atoi((const char *)tmp);
+ switch (ret) {
case PAM_AUTHTOK_EXPIRED:
/* fall through, since new token is required in this case */
case PAM_NEW_AUTHTOK_REQD:
- _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set",
+ _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set",
PAM_WINBIND_NEW_AUTHTOK_REQD);
- _pam_log(LOG_NOTICE, "user '%s' needs new password", username);
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username);
/* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */
- return PAM_NEW_AUTHTOK_REQD;
+ ret = PAM_NEW_AUTHTOK_REQD;
+ goto out;
default:
- _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success");
- _pam_log(LOG_NOTICE, "user '%s' granted access", username);
- return PAM_SUCCESS;
+ _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success");
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username);
+ ret = PAM_SUCCESS;
+ goto out;
}
}
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted access", username);
- return PAM_SUCCESS;
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username);
+ ret = PAM_SUCCESS;
+ goto out;
default:
/* we don't know anything about this return value */
- _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')",
- retval, username);
- return PAM_SERVICE_ERR;
+ _pam_log(pamh, ctrl, LOG_ERR, "internal module error (ret = %d, user = '%s')",
+ ret, username);
+ ret = PAM_SERVICE_ERR;
+ goto out;
}
/* should not be reached */
- return PAM_IGNORE;
+ ret = PAM_IGNORE;
+
+ out:
+
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret);
+
+ return ret;
}
PAM_EXTERN
int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
+ int ret = PAM_SYSTEM_ERR;
+ dictionary *d = NULL;
+
/* parse arguments */
- int ctrl = _pam_parse(argc, argv, NULL);
+ int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
- return PAM_SYSTEM_ERR;
+ ret = PAM_SYSTEM_ERR;
+ goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", pamh, ctrl, flags);
- return PAM_SUCCESS;
+ ret = PAM_SUCCESS;
+
+ out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret);
+
+ return ret;
}
PAM_EXTERN
@@ -1079,13 +1789,13 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags,
int retval = PAM_SUCCESS;
/* parse arguments */
- int ctrl = _pam_parse(argc, argv, &d);
+ int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
retval = PAM_SYSTEM_ERR;
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", pamh, ctrl, flags);
if (!(flags & PAM_DELETE_CRED)) {
retval = PAM_SUCCESS;
@@ -1105,32 +1815,31 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags,
ZERO_STRUCT(response);
retval = pam_get_user(pamh, &user, "Username: ");
- if (retval == PAM_SUCCESS) {
- if (user == NULL) {
- _pam_log(LOG_ERR, "username was NULL!");
- retval = PAM_USER_UNKNOWN;
- goto out;
- }
- if (retval == PAM_SUCCESS) {
- _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", user);
- }
- } else {
- _pam_log_debug(ctrl, LOG_DEBUG, "could not identify user");
+ if (retval) {
+ _pam_log(pamh, ctrl, LOG_ERR, "could not identify user");
+ goto out;
+ }
+
+ if (user == NULL) {
+ _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!");
+ retval = PAM_USER_UNKNOWN;
goto out;
}
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user);
+
ccname = pam_getenv(pamh, "KRB5CCNAME");
if (ccname == NULL) {
- _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment");
- retval = PAM_SUCCESS;
- goto out;
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment");
}
strncpy(request.data.logoff.user, user,
sizeof(request.data.logoff.user) - 1);
- strncpy(request.data.logoff.krb5ccname, ccname,
- sizeof(request.data.logoff.krb5ccname) - 1);
+ if (ccname) {
+ strncpy(request.data.logoff.krb5ccname, ccname,
+ sizeof(request.data.logoff.krb5ccname) - 1);
+ }
pwd = getpwnam(user);
if (pwd == NULL) {
@@ -1148,9 +1857,55 @@ out:
if (d) {
iniparser_freedict(d);
}
+
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval);
+
return retval;
}
+/**
+ * evaluate whether we need to re-authenticate with kerberos after a password change
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param user The username
+ *
+ * @return boolean Returns True if required, False if not.
+ */
+
+static BOOL _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user)
+{
+
+ /* Make sure that we only do this if
+ * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok)
+ * b) any later password change via the "passwd" command if done by the user itself
+ */
+
+ char *new_authtok_reqd_during_auth = NULL;
+ struct passwd *pwd = NULL;
+
+ if (!(ctrl & WINBIND_KRB5_AUTH)) {
+ return False;
+ }
+
+ _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth);
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL);
+
+ if (new_authtok_reqd_during_auth) {
+ return True;
+ }
+
+ pwd = getpwnam(user);
+ if (!pwd) {
+ return False;
+ }
+
+ if (getuid() == pwd->pw_uid) {
+ return True;
+ }
+
+ return False;
+}
PAM_EXTERN
@@ -1158,7 +1913,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
int argc, const char **argv)
{
unsigned int lctrl;
- int retval;
+ int ret;
unsigned int ctrl;
/* <DO NOT free() THESE> */
@@ -1170,14 +1925,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
int retry = 0;
dictionary *d = NULL;
+ char *username_ret = NULL;
+ struct winbindd_response response;
- ctrl = _pam_parse(argc, argv, &d);
+ ZERO_STRUCT(response);
+
+ ctrl = _pam_parse(pamh, flags, argc, argv, &d);
if (ctrl == -1) {
- retval = PAM_SYSTEM_ERR;
+ ret = PAM_SYSTEM_ERR;
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags);
+ _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", pamh, ctrl, flags);
/* clearing offline bit for the auth in the password change */
ctrl &= ~WINBIND_CACHED_LOGIN;
@@ -1185,31 +1944,29 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/*
* First get the name of a user
*/
- retval = pam_get_user(pamh, &user, "Username: ");
- if (retval == PAM_SUCCESS) {
- if (user == NULL) {
- _pam_log(LOG_ERR, "username was NULL!");
- retval = PAM_USER_UNKNOWN;
- goto out;
- }
- if (retval == PAM_SUCCESS) {
- _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained",
- user);
- }
- } else {
- _pam_log_debug(ctrl, LOG_DEBUG,
+ ret = pam_get_user(pamh, &user, "Username: ");
+ if (ret) {
+ _pam_log(pamh, ctrl, LOG_ERR,
"password - could not identify user");
goto out;
}
+ if (user == NULL) {
+ _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!");
+ ret = PAM_USER_UNKNOWN;
+ goto out;
+ }
+
+ _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user);
+
/* check if this is really a user in winbindd, not only in NSS */
- retval = valid_user(user, pamh, ctrl);
- switch (retval) {
+ ret = valid_user(pamh, ctrl, user);
+ switch (ret) {
case 1:
- retval = PAM_USER_UNKNOWN;
+ ret = PAM_USER_UNKNOWN;
goto out;
case -1:
- retval = PAM_SYSTEM_ERR;
+ ret = PAM_SYSTEM_ERR;
goto out;
default:
break;
@@ -1221,15 +1978,14 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
*/
if (flags & PAM_PRELIM_CHECK) {
-
time_t pwdlastset_prelim = 0;
/* instruct user what is happening */
#define greeting "Changing password for "
Announce = (char *) malloc(sizeof(greeting) + strlen(user));
if (Announce == NULL) {
- _pam_log(LOG_CRIT, "password - out of memory");
- retval = PAM_BUF_ERR;
+ _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory");
+ ret = PAM_BUF_ERR;
goto out;
}
(void) strcpy(Announce, greeting);
@@ -1237,33 +1993,35 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
#undef greeting
lctrl = ctrl | WINBIND__OLD_PASSWORD;
- retval = _winbind_read_password(pamh, lctrl,
+ ret = _winbind_read_password(pamh, lctrl,
Announce,
"(current) NT password: ",
NULL,
(const char **) &pass_old);
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_NOTICE, "password - (old) token not obtained");
+ if (ret != PAM_SUCCESS) {
+ _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained");
goto out;
}
+
/* verify that this is the password for this user */
- retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False, &pwdlastset_prelim);
+ ret = winbind_auth_request(pamh, ctrl, user, pass_old,
+ NULL, NULL, &response, &pwdlastset_prelim, NULL);
- if (retval != PAM_ACCT_EXPIRED &&
- retval != PAM_AUTHTOK_EXPIRED &&
- retval != PAM_NEW_AUTHTOK_REQD &&
- retval != PAM_SUCCESS) {
+ if (ret != PAM_ACCT_EXPIRED &&
+ ret != PAM_AUTHTOK_EXPIRED &&
+ ret != PAM_NEW_AUTHTOK_REQD &&
+ ret != PAM_SUCCESS) {
pass_old = NULL;
goto out;
}
pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL);
- retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
+ ret = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
pass_old = NULL;
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_CRIT, "failed to set PAM_OLDAUTHTOK");
+ if (ret != PAM_SUCCESS) {
+ _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK");
}
} else if (flags & PAM_UPDATE_AUTHTOK) {
@@ -1277,35 +2035,34 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* get the old token back.
*/
- retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
- (const void **) &pass_old);
+ ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old);
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_NOTICE, "user not authenticated");
+ if (ret != PAM_SUCCESS) {
+ _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated");
goto out;
}
- lctrl = ctrl;
+ lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG;
if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) {
lctrl |= WINBIND_USE_FIRST_PASS_ARG;
}
retry = 0;
- retval = PAM_AUTHTOK_ERR;
- while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
+ ret = PAM_AUTHTOK_ERR;
+ while ((ret != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
/*
* use_authtok is to force the use of a previously entered
* password -- needed for pluggable password strength checking
*/
- retval = _winbind_read_password(pamh, lctrl,
+ ret = _winbind_read_password(pamh, lctrl,
NULL,
"Enter new NT password: ",
"Retype new NT password: ",
(const char **) &pass_new);
- if (retval != PAM_SUCCESS) {
- _pam_log_debug(ctrl, LOG_ALERT
+ if (ret != PAM_SUCCESS) {
+ _pam_log_debug(pamh, ctrl, LOG_ALERT
,"password - new password not obtained");
pass_old = NULL;/* tidy up */
goto out;
@@ -1326,37 +2083,65 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* By reaching here we have approved the passwords and must now
* rebuild the password database file.
*/
- pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update);
+ _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET,
+ &pwdlastset_update);
- retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update);
- if (retval) {
+ ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update);
+ if (ret) {
_pam_overwrite(pass_new);
_pam_overwrite(pass_old);
pass_old = pass_new = NULL;
goto out;
}
- /* just in case we need krb5 creds after a password change over msrpc */
+ if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) {
- if (ctrl & WINBIND_KRB5_AUTH) {
+ const char *member = get_member_from_config(pamh, argc, argv, ctrl, d);
+ const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d);
- const char *member = get_member_from_config(argc, argv, ctrl, d);
- const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d);
-
- retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL);
+ ret = winbind_auth_request(pamh, ctrl, user, pass_new,
+ member, cctype, &response, NULL, &username_ret);
_pam_overwrite(pass_new);
_pam_overwrite(pass_old);
pass_old = pass_new = NULL;
+
+ if (ret == PAM_SUCCESS) {
+
+ /* warn a user if the password is about to expire soon */
+ _pam_warn_password_expiry(pamh, ctrl, &response, NULL);
+
+ /* set some info3 info for other modules in the stack */
+ _pam_set_data_info3(pamh, ctrl, &response);
+
+ /* put krb5ccname into env */
+ _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname);
+
+ if (username_ret) {
+ pam_set_item (pamh, PAM_USER, username_ret);
+ _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret);
+ free(username_ret);
+ }
+ }
+
+ goto out;
}
} else {
- retval = PAM_SERVICE_ERR;
+ ret = PAM_SERVICE_ERR;
}
out:
if (d) {
iniparser_freedict(d);
}
- return retval;
+
+ /* Deal with offline errors. */
+ PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS");
+ PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND");
+ PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED");
+
+ _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret);
+
+ return ret;
}
#ifdef PAM_STATIC
@@ -1379,7 +2164,7 @@ struct pam_module _pam_winbind_modstruct = {
* Copyright (c) Andrew Tridgell <tridge@samba.org> 2000
* Copyright (c) Tim Potter <tpot@samba.org> 2000
* Copyright (c) Andrew Bartlettt <abartlet@samba.org> 2002
- * Copyright (c) Guenther Deschner <gd@samba.org> 2005-2006
+ * Copyright (c) Guenther Deschner <gd@samba.org> 2005-2007
* Copyright (c) Jan Rêkorajski 1999.
* Copyright (c) Andrew G. Morgan 1996-8.
* Copyright (c) Alex O. Yuriev, 1996.
diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
index bfa9ebf855b..73da2826cab 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -4,23 +4,9 @@
Shirish Kalele 2000
*/
-#ifdef HAVE_FEATURES_H
-#include <features.h>
-#endif
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <time.h>
-
-#include <config.h>
+#include "lib/replace/replace.h"
+#include "system/syslog.h"
+#include "system/time.h"
#define MODULE_NAME "pam_winbind"
#define PAM_SM_AUTH
@@ -33,7 +19,7 @@
#include <iniparser.h>
-#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) || defined(AIX)
+#ifndef LINUX
/* Solaris always uses dynamic pam modules */
#define PAM_EXTERN extern
@@ -43,7 +29,7 @@
#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR
#endif
-#endif
+#endif /* defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) || defined(AIX) */
#ifdef HAVE_SECURITY_PAM_MODULES_H
#include <security/pam_modules.h>
@@ -82,6 +68,10 @@ do { \
#define _pam_drop(X) SAFE_FREE(X)
#define x_strdup(s) ( (s) ? strdup(s):NULL )
+#endif /* HAVE_SECURITY__PAM_MACROS_H */
+
+#ifdef HAVE_SECURITY_PAM_EXT_H
+#include <security/pam_ext.h>
#endif
#define WINBIND_DEBUG_ARG (1<<0)
@@ -95,6 +85,8 @@ do { \
#define WINBIND_KRB5_CCACHE_TYPE (1<<8)
#define WINBIND_CACHED_LOGIN (1<<9)
#define WINBIND_CONFIG_FILE (1<<10)
+#define WINBIND_SILENT (1<<11)
+#define WINBIND_DEBUG_STATE (1<<12)
/*
* here is the string to inform the user that the new passwords they
@@ -107,8 +99,10 @@ do { \
#define off(x, y) (!(x & y))
#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH "PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH"
#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR"
#define PAM_WINBIND_LOGONSCRIPT "PAM_WINBIND_LOGONSCRIPT"
+#define PAM_WINBIND_LOGONSERVER "PAM_WINBIND_LOGONSERVER"
#define PAM_WINBIND_PROFILEPATH "PAM_WINBIND_PROFILEPATH"
#define PAM_WINBIND_PWD_LAST_SET "PAM_WINBIND_PWD_LAST_SET"
@@ -118,44 +112,60 @@ do { \
#include "winbind_client.h"
-#define PAM_WB_REMARK_DIRECT(h,x)\
+#define PAM_WB_REMARK_DIRECT(h,f,x)\
{\
const char *error_string = NULL; \
error_string = _get_ntstatus_error_string(x);\
if (error_string != NULL) {\
- _make_remark(h, PAM_ERROR_MSG, error_string);\
+ _make_remark(h, f, PAM_ERROR_MSG, error_string);\
} else {\
- _make_remark(h, PAM_ERROR_MSG, x);\
+ _make_remark(h, f, PAM_ERROR_MSG, x);\
};\
};
-#define PAM_WB_REMARK_DIRECT_RET(h,x)\
+#define PAM_WB_REMARK_DIRECT_RET(h,f,x)\
{\
const char *error_string = NULL; \
error_string = _get_ntstatus_error_string(x);\
if (error_string != NULL) {\
- _make_remark(h, PAM_ERROR_MSG, error_string);\
+ _make_remark(h, f, PAM_ERROR_MSG, error_string);\
return ret;\
};\
- _make_remark(h, PAM_ERROR_MSG, x);\
+ _make_remark(h, f, PAM_ERROR_MSG, x);\
return ret;\
};
-
-#define PAM_WB_REMARK_CHECK_RESPONSE_RET(h,x,y)\
+
+#define PAM_WB_REMARK_CHECK_RESPONSE(h,f,x,y)\
+{\
+ const char *ntstatus = x.data.auth.nt_status_string; \
+ const char *error_string = NULL; \
+ if (!strcasecmp(ntstatus,y)) {\
+ error_string = _get_ntstatus_error_string(y);\
+ if (error_string != NULL) {\
+ _make_remark(h, f, PAM_ERROR_MSG, error_string);\
+ };\
+ if (x.data.auth.error_string[0] != '\0') {\
+ _make_remark(h, f, PAM_ERROR_MSG, x.data.auth.error_string);\
+ };\
+ _make_remark(h, f, PAM_ERROR_MSG, y);\
+ };\
+};
+
+#define PAM_WB_REMARK_CHECK_RESPONSE_RET(h,f,x,y)\
{\
const char *ntstatus = x.data.auth.nt_status_string; \
const char *error_string = NULL; \
if (!strcasecmp(ntstatus,y)) {\
error_string = _get_ntstatus_error_string(y);\
if (error_string != NULL) {\
- _make_remark(h, PAM_ERROR_MSG, error_string);\
+ _make_remark(h, f, PAM_ERROR_MSG, error_string);\
return ret;\
};\
if (x.data.auth.error_string[0] != '\0') {\
- _make_remark(h, PAM_ERROR_MSG, x.data.auth.error_string);\
+ _make_remark(h, f, PAM_ERROR_MSG, x.data.auth.error_string);\
return ret;\
};\
- _make_remark(h, PAM_ERROR_MSG, y);\
+ _make_remark(h, f, PAM_ERROR_MSG, y);\
return ret;\
};\
};
@@ -173,4 +183,7 @@ do { \
/* from include/rpc_netlogon.h */
#define LOGON_CACHED_ACCOUNT 0x00000004
+#define LOGON_GRACE_LOGON 0x01000000
+#define PAM_WB_CACHED_LOGON(x) (x & LOGON_CACHED_ACCOUNT)
+#define PAM_WB_GRACE_LOGON(x) ((LOGON_CACHED_ACCOUNT|LOGON_GRACE_LOGON) == ( x & (LOGON_CACHED_ACCOUNT|LOGON_GRACE_LOGON)))
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c
index de1edf054d1..afb62027544 100644
--- a/source/nsswitch/wb_client.c
+++ b/source/nsswitch/wb_client.c
@@ -35,7 +35,7 @@ NSS_STATUS winbindd_request_response(int req_type,
/* Call winbindd to convert a name to a sid */
BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
- enum SID_NAME_USE *name_type)
+ enum lsa_SidType *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -56,7 +56,7 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
&response)) == NSS_STATUS_SUCCESS) {
if (!string_to_sid(sid, response.data.sid.sid))
return False;
- *name_type = (enum SID_NAME_USE)response.data.sid.type;
+ *name_type = (enum lsa_SidType)response.data.sid.type;
}
return result == NSS_STATUS_SUCCESS;
@@ -66,7 +66,7 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **domain, const char **name,
- enum SID_NAME_USE *name_type)
+ enum lsa_SidType *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -105,7 +105,7 @@ BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
}
}
- *name_type = (enum SID_NAME_USE)response.data.name.type;
+ *name_type = (enum lsa_SidType)response.data.name.type;
DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
sid_string_static(sid), response.data.name.dom_name,
@@ -113,6 +113,116 @@ BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
return True;
}
+BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char ***names, enum lsa_SidType **types)
+{
+ size_t i, buflen;
+ ssize_t len;
+ char *ridlist;
+ char *p;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if (num_rids == 0) {
+ return False;
+ }
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.sid, sid_string_static(domain_sid));
+
+ len = 0;
+ buflen = 0;
+ ridlist = NULL;
+
+ for (i=0; i<num_rids; i++) {
+ sprintf_append(mem_ctx, &ridlist, &len, &buflen,
+ "%ld\n", rids[i]);
+ }
+
+ if ((num_rids != 0) && (ridlist == NULL)) {
+ return False;
+ }
+
+ request.extra_data.data = ridlist;
+ request.extra_len = strlen(ridlist)+1;
+
+ result = winbindd_request_response(WINBINDD_LOOKUPRIDS,
+ &request, &response);
+
+ TALLOC_FREE(ridlist);
+
+ if (result != NSS_STATUS_SUCCESS) {
+ return False;
+ }
+
+ *domain_name = talloc_strdup(mem_ctx, response.data.domain_name);
+
+ *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+
+ if ((*names == NULL) || (*types == NULL)) {
+ goto fail;
+ }
+
+ p = (char *)response.extra_data.data;
+
+ for (i=0; i<num_rids; i++) {
+ char *q;
+
+ if (*p == '\0') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ (*types)[i] = (enum lsa_SidType)strtoul(p, &q, 10);
+
+ if (*q != ' ') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ p = q+1;
+
+ q = strchr(p, '\n');
+ if (q == NULL) {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ *q = '\0';
+
+ (*names)[i] = talloc_strdup(*names, p);
+
+ p = q+1;
+ }
+
+ if (*p != '\0') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ SAFE_FREE(response.extra_data.data);
+
+ return True;
+
+ fail:
+ TALLOC_FREE(*names);
+ TALLOC_FREE(*types);
+ return False;
+}
+
/* Call winbindd to convert SID to uid */
BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
@@ -247,6 +357,74 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
return (result == NSS_STATUS_SUCCESS);
}
+/* Call winbindd to convert SID to uid */
+
+BOOL winbind_sids_to_unixids(struct id_map *ids, int num_ids)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
+ DOM_SID *sids;
+ int i;
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ request.extra_len = num_ids * sizeof(DOM_SID);
+
+ sids = (DOM_SID *)SMB_MALLOC(request.extra_len);
+ for (i = 0; i < num_ids; i++) {
+ sid_copy(&sids[i], ids[i].sid);
+ }
+
+ request.extra_data.data = (char *)sids;
+
+ /* Make request */
+
+ result = winbindd_request_response(WINBINDD_SIDS_TO_XIDS, &request, &response);
+
+ /* Copy out result */
+
+ if (result == NSS_STATUS_SUCCESS) {
+ struct unixid *wid = (struct unixid *)response.extra_data.data;
+
+ for (i = 0; i < num_ids; i++) {
+ if (wid[i].type == -1) {
+ ids[i].status = ID_UNMAPPED;
+ } else {
+ ids[i].status = ID_MAPPED;
+ ids[i].xid.type = wid[i].type;
+ ids[i].xid.id = wid[i].id;
+ }
+ }
+ }
+
+ SAFE_FREE(request.extra_data.data);
+ SAFE_FREE(response.extra_data.data);
+
+ return (result == NSS_STATUS_SUCCESS);
+}
+
+BOOL winbind_idmap_dump_maps(TALLOC_CTX *memctx, const char *file)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ request.extra_data.data = SMB_STRDUP(file);
+ request.extra_len = strlen(request.extra_data.data) + 1;
+
+ result = winbindd_request_response(WINBINDD_DUMP_MAPS, &request, &response);
+
+ SAFE_FREE(request.extra_data.data);
+ return (result == NSS_STATUS_SUCCESS);
+}
+
BOOL winbind_allocate_uid(uid_t *uid)
{
struct winbindd_request request;
@@ -297,126 +475,68 @@ BOOL winbind_allocate_gid(gid_t *gid)
return True;
}
-/* Fetch the list of groups a user is a member of from winbindd. This is
- used by winbind_getgroups. */
-
-static int wb_getgroups(const char *user, gid_t **groups)
+BOOL winbind_set_mapping(const struct id_map *map)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
- /* Call winbindd */
+ /* Initialise request */
ZERO_STRUCT(request);
- fstrcpy(request.data.username, user);
-
ZERO_STRUCT(response);
- result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
+ /* Make request */
- if (result == NSS_STATUS_SUCCESS) {
-
- /* Return group list. Don't forget to free the group list
- when finished. */
+ request.data.dual_idmapset.id = map->xid.id;
+ request.data.dual_idmapset.type = map->xid.type;
+ sid_to_string(request.data.dual_idmapset.sid, map->sid);
- *groups = (gid_t *)response.extra_data.data;
- return response.data.num_entries;
- }
+ result = winbindd_request_response(WINBINDD_SET_MAPPING, &request, &response);
- return -1;
+ return (result == NSS_STATUS_SUCCESS);
}
-/* Call winbindd to initialise group membership. This is necessary for
- some systems (i.e RH5.2) that do not have an initgroups function as part
- of the nss extension. In RH5.2 this is implemented using getgrent()
- which can be amazingly inefficient as well as having problems with
- username case. */
-
-int winbind_initgroups(char *user, gid_t gid)
+BOOL winbind_set_uid_hwm(unsigned long id)
{
- gid_t *groups = NULL;
+ struct winbindd_request request;
+ struct winbindd_response response;
int result;
- /* Call normal initgroups if we are a local user */
-
- if (!strchr(user, *lp_winbind_separator())) {
- return initgroups(user, gid);
- }
-
- result = wb_getgroups(user, &groups);
-
- DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
- result == -1 ? "FAIL" : "SUCCESS"));
-
- if (result != -1) {
- int ngroups = result, i;
- BOOL is_member = False;
-
- /* Check to see if the passed gid is already in the list */
-
- for (i = 0; i < ngroups; i++) {
- if (groups[i] == gid) {
- is_member = True;
- }
- }
-
- /* Add group to list if necessary */
-
- if (!is_member) {
- groups = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
- if (!groups) {
- errno = ENOMEM;
- result = -1;
- goto done;
- }
-
- groups[ngroups] = gid;
- ngroups++;
- }
+ /* Initialise request */
- /* Set the groups */
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
- if (sys_setgroups(ngroups, groups) == -1) {
- errno = EPERM;
- result = -1;
- goto done;
- }
+ /* Make request */
- } else {
-
- /* The call failed. Set errno to something so we don't get
- a bogus value from the last failed system call. */
+ request.data.dual_idmapset.id = id;
+ request.data.dual_idmapset.type = ID_TYPE_UID;
- errno = EIO;
- }
+ result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
- /* Free response data if necessary */
+ return (result == NSS_STATUS_SUCCESS);
+}
- done:
- SAFE_FREE(groups);
+BOOL winbind_set_gid_hwm(unsigned long id)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
- return result;
-}
+ /* Initialise request */
-/* Return a list of groups the user is a member of. This function is
- useful for large systems where inverting the group database would be too
- time consuming. If size is zero, list is not modified and the total
- number of groups for the user is returned. */
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
-int winbind_getgroups(const char *user, gid_t **list)
-{
- /*
- * Don't do the lookup if the name has no separator _and_ we are not in
- * 'winbind use default domain' mode.
- */
+ /* Make request */
- if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
- return -1;
+ request.data.dual_idmapset.id = id;
+ request.data.dual_idmapset.type = ID_TYPE_GID;
- /* Fetch list of groups */
+ result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
- return wb_getgroups(user, list);
+ return (result == NSS_STATUS_SUCCESS);
}
/**********************************************************************
diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c
index a6b6bd60997..05d2a660e73 100644
--- a/source/nsswitch/wb_common.c
+++ b/source/nsswitch/wb_common.c
@@ -26,6 +26,10 @@
#include "winbind_client.h"
+BOOL winbind_env_set( void );
+BOOL winbind_off( void );
+BOOL winbind_on( void );
+
/* Global variables. These are effectively the client state information */
int winbindd_fd = -1; /* fd for winbindd socket */
@@ -53,7 +57,7 @@ void init_request(struct winbindd_request *request, int request_type)
/* Initialise a response structure */
-void init_response(struct winbindd_response *response)
+static void init_response(struct winbindd_response *response)
{
/* Initialise return value */
@@ -71,8 +75,6 @@ void close_sock(void)
}
#define CONNECT_TIMEOUT 30
-#define WRITE_TIMEOUT CONNECT_TIMEOUT
-#define READ_TIMEOUT CONNECT_TIMEOUT
/* Make sure socket handle isn't stdin, stdout or stderr */
#define RECURSION_LIMIT 3
@@ -324,7 +326,7 @@ static int winbind_open_pipe_sock(int recursing)
request.flags = WBFLAG_RECURSE;
if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) {
int fd;
- if ((fd = winbind_named_pipe_sock(response.extra_data.data)) != -1) {
+ if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) {
close(winbindd_fd);
winbindd_fd = fd;
}
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 69d7a1069f9..3ae97cfea0a 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -151,6 +151,34 @@ static BOOL wbinfo_get_userinfo(char *user)
return True;
}
+/* pull grent for a given group */
+static BOOL wbinfo_get_groupinfo(char *group)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ /* Send request */
+
+ fstrcpy(request.data.groupname, group);
+
+ result = winbindd_request_response(WINBINDD_GETGRNAM, &request,
+ &response);
+
+ if ( result != NSS_STATUS_SUCCESS)
+ return False;
+
+ d_printf( "%s:%s:%d\n",
+ response.data.gr.gr_name,
+ response.data.gr.gr_passwd,
+ response.data.gr.gr_gid );
+
+ return True;
+}
+
/* List groups a user is a member of */
static BOOL wbinfo_get_usergroups(char *user)
@@ -201,7 +229,7 @@ static BOOL wbinfo_get_usersids(char *user_sid)
if (result != NSS_STATUS_SUCCESS)
return False;
- s = response.extra_data.data;
+ s = (const char *)response.extra_data.data;
for (i = 0; i < response.data.num_entries; i++) {
d_printf("%s\n", s);
s += strlen(s) + 1;
@@ -380,7 +408,10 @@ static BOOL wbinfo_domain_info(const char *domain_name)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- fstrcpy(request.domain_name, domain_name);
+ if ((strequal(domain_name, ".")) || (domain_name[0] == '\0'))
+ fstrcpy(request.domain_name, get_winbind_domain());
+ else
+ fstrcpy(request.domain_name, domain_name);
/* Send request */
@@ -605,6 +636,82 @@ static BOOL wbinfo_lookupsid(char *sid)
return True;
}
+/* Lookup a list of RIDs */
+
+static BOOL wbinfo_lookuprids(char *domain, char *arg)
+{
+ size_t i;
+ DOM_SID sid;
+ int num_rids;
+ uint32 *rids;
+ const char *p;
+ char ridstr[32];
+ const char **names;
+ enum lsa_SidType *types;
+ const char *domain_name;
+ TALLOC_CTX *mem_ctx;
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0'))
+ fstrcpy(request.domain_name, get_winbind_domain());
+ else
+ fstrcpy(request.domain_name, domain);
+
+ /* Send request */
+
+ if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) !=
+ NSS_STATUS_SUCCESS) {
+ d_printf("Could not get domain sid for %s\n", request.domain_name);
+ return False;
+ }
+
+ if (!string_to_sid(&sid, response.data.domain_info.sid)) {
+ d_printf("Could not convert %s to sid\n", response.data.domain_info.sid);
+ return False;
+ }
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ d_printf("talloc_new failed\n");
+ return False;
+ }
+
+ num_rids = 0;
+ rids = NULL;
+ p = arg;
+
+ while (next_token(&p, ridstr, " ,\n", sizeof(ridstr))) {
+ uint32 rid = strtoul(ridstr, NULL, 10);
+ ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids);
+ }
+
+ if (rids == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return False;
+ }
+
+ if (!winbind_lookup_rids(mem_ctx, &sid, num_rids, rids,
+ &domain_name, &names, &types)) {
+ d_printf("winbind_lookup_rids failed\n");
+ TALLOC_FREE(mem_ctx);
+ return False;
+ }
+
+ d_printf("Domain: %s\n", domain_name);
+
+ for (i=0; i<num_rids; i++) {
+ d_printf("%8d: %s (%s)\n", rids[i], names[i],
+ sid_type_lookup(types[i]));
+ }
+
+ TALLOC_FREE(mem_ctx);
+ return True;
+}
+
/* Convert string to sid */
static BOOL wbinfo_lookupname(char *name)
@@ -905,9 +1012,9 @@ static BOOL print_domain_users(const char *domain)
ZERO_STRUCT(response);
if (domain) {
- /* '.' is the special sign for our own domwin */
+ /* '.' is the special sign for our own domain */
if ( strequal(domain, ".") )
- fstrcpy( request.domain_name, lp_workgroup() );
+ fstrcpy( request.domain_name, get_winbind_domain() );
else
fstrcpy( request.domain_name, domain );
}
@@ -945,7 +1052,7 @@ static BOOL print_domain_groups(const char *domain)
if (domain) {
if ( strequal(domain, ".") )
- fstrcpy( request.domain_name, lp_workgroup() );
+ fstrcpy( request.domain_name, get_winbind_domain() );
else
fstrcpy( request.domain_name, domain );
}
@@ -1089,10 +1196,11 @@ enum {
OPT_ALLOCATE_GID,
OPT_SEPARATOR,
OPT_LIST_ALL_DOMAINS,
- OPT_LIST_OWN_DOMAIN
+ OPT_LIST_OWN_DOMAIN,
+ OPT_GROUP_INFO,
};
-int main(int argc, char **argv)
+int main(int argc, char **argv, char **envp)
{
int opt;
@@ -1114,6 +1222,7 @@ int main(int argc, char **argv)
{ "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" },
{ "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" },
{ "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" },
+ { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" },
{ "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" },
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
@@ -1129,6 +1238,7 @@ int main(int argc, char **argv)
{ "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
{ "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
{ "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
+ { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
{ "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
@@ -1207,6 +1317,12 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case 'R':
+ if (!wbinfo_lookuprids(opt_domain_name, string_arg)) {
+ d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg);
+ goto done;
+ }
+ break;
case 'n':
if (!wbinfo_lookupname(string_arg)) {
d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
@@ -1295,6 +1411,13 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case OPT_GROUP_INFO:
+ if ( !wbinfo_get_groupinfo(string_arg)) {
+ d_fprintf(stderr, "Could not get info for "
+ "group %s\n", string_arg);
+ goto done;
+ }
+ break;
case 'r':
if (!wbinfo_get_usergroups(string_arg)) {
d_fprintf(stderr, "Could not get groups for user %s\n",
diff --git a/source/nsswitch/winbind_nss.h b/source/nsswitch/winbind_nss.h
index 5416ae211e3..3bef6ca5954 100644
--- a/source/nsswitch/winbind_nss.h
+++ b/source/nsswitch/winbind_nss.h
@@ -56,7 +56,15 @@ typedef enum nss_status NSS_STATUS;
#include "nsswitch/winbind_nss_hpux.h"
-#else /* Nothing's defined. Neither gnu nor sun nor hp */
+#elif defined(__NetBSD__) && defined(HAVE_GETPWENT_R)
+
+/*
+ * NetBSD 3 and newer
+ */
+
+#include "nsswitch/winbind_nss_netbsd.h"
+
+#else /* Nothing's defined. Neither gnu nor netbsd nor sun nor hp */
typedef enum
{
diff --git a/source/nsswitch/winbind_nss_aix.c b/source/nsswitch/winbind_nss_aix.c
index 5b3aaeb8d77..6a39b4b7c41 100644
--- a/source/nsswitch/winbind_nss_aix.c
+++ b/source/nsswitch/winbind_nss_aix.c
@@ -45,13 +45,8 @@
*/
-#include <stdlib.h>
-#include <string.h>
-#include <usersec.h>
-#include <errno.h>
-#include <stdarg.h>
-
#include "winbind_client.h"
+#include <usersec.h>
#define WB_AIX_ENCODED '_'
diff --git a/source/nsswitch/winbind_nss_config.h b/source/nsswitch/winbind_nss_config.h
index f9d38526604..d595631362b 100644
--- a/source/nsswitch/winbind_nss_config.h
+++ b/source/nsswitch/winbind_nss_config.h
@@ -33,55 +33,13 @@
/* Include header files from data in config.h file */
#ifndef NO_CONFIG_H
-#include <config.h>
+#include "lib/replace/replace.h"
#endif
-#include <stdio.h>
+#include "system/passwd.h"
+#include "system/filesys.h"
+#include "system/network.h"
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_UNIXSOCKET
-#include <sys/un.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#else
-#ifdef HAVE_SYS_FCNTL_H
-#include <sys/fcntl.h>
-#endif
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <pwd.h>
#include "nsswitch/winbind_nss.h"
/* I'm trying really hard not to include anything from smb.h with the
@@ -95,8 +53,8 @@ typedef char pstring[PSTRING_LEN];
typedef char fstring[FSTRING_LEN];
#endif
-#ifndef _BOOL
-#define _BOOL /* So we don't typedef BOOL again in vfs.h */
+#ifndef _UPPER_BOOL
+#define _UPPER_BOOL
#define False (0)
#define True (1)
#define Auto (2)
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index 78a39f28731..fa74194aa9d 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -30,10 +30,64 @@
#define MAX_GETPWENT_USERS 250
#define MAX_GETGRENT_USERS 250
+NSS_STATUS _nss_winbind_setpwent(void);
+NSS_STATUS _nss_winbind_endpwent(void);
+NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result,
+ char *buffer, size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result,
+ char *buffer, size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_setgrent(void);
+NSS_STATUS _nss_winbind_endgrent(void);
+NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result,
+ char *buffer, size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
+ long int *size, gid_t **groups,
+ long int limit, int *errnop);
+NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids,
+ int *num_groups, char *buffer, size_t buf_size,
+ int *errnop);
+NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop);
+NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop);
+NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
+ size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
+ size_t buflen, int *errnop);
+
/* Prototypes from wb_common.c */
extern int winbindd_fd;
+#ifdef DEBUG_NSS
+static const char *nss_err_str(NSS_STATUS ret) {
+ switch (ret) {
+ case NSS_STATUS_TRYAGAIN:
+ return "NSS_STATUS_TRYAGAIN";
+ case NSS_STATUS_SUCCESS:
+ return "NSS_STATUS_SUCCESS";
+ case NSS_STATUS_NOTFOUND:
+ return "NSS_STATUS_NOTFOUND";
+ case NSS_STATUS_UNAVAIL:
+ return "NSS_STATUS_UNAVAIL";
+ case NSS_STATUS_RETURN:
+ return "NSS_STATUS_RETURN";
+ default:
+ return "UNKNOWN RETURN CODE!!!!!!!";
+ }
+}
+#endif
+
/* Allocate some space from the nss static buffer. The buffer and buflen
are the pointers passed in by the C library to the _nss_ntdom_*
functions. */
@@ -62,7 +116,7 @@ static char *get_static(char **buffer, size_t *buflen, size_t len)
lib/util_str.c as I really don't want to have to link in any other
objects if I can possibly avoid it. */
-BOOL next_token(char **ptr,char *buff,const char *sep, size_t bufsize)
+static BOOL next_token(char **ptr,char *buff,const char *sep, size_t bufsize)
{
char *s;
BOOL quoted;
@@ -294,6 +348,7 @@ static int num_pw_cache; /* Current size of pwd cache */
NSS_STATUS
_nss_winbind_setpwent(void)
{
+ NSS_STATUS ret;
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: setpwent\n", getpid());
#endif
@@ -303,7 +358,12 @@ _nss_winbind_setpwent(void)
free_response(&getpwent_response);
}
- return winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);
+ ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
+ return ret;
}
/* Close ntdom password database "file pointer" */
@@ -311,6 +371,7 @@ _nss_winbind_setpwent(void)
NSS_STATUS
_nss_winbind_endpwent(void)
{
+ NSS_STATUS ret;
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: endpwent\n", getpid());
#endif
@@ -320,7 +381,12 @@ _nss_winbind_endpwent(void)
free_response(&getpwent_response);
}
- return winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);
+ ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
+ return ret;
}
/* Fetch the next password entry from ntdom password database */
@@ -370,12 +436,14 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
return_result:
- pw_cache = getpwent_response.extra_data.data;
+ pw_cache = (struct winbindd_pw *)
+ getpwent_response.extra_data.data;
/* Check data is valid */
if (pw_cache == NULL) {
- return NSS_STATUS_NOTFOUND;
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
}
ret = fill_pwent(result, &pw_cache[ndx_pw_cache],
@@ -386,7 +454,7 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
if (ret == NSS_STATUS_TRYAGAIN) {
called_again = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
*errnop = errno = 0;
@@ -400,7 +468,11 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
free_response(&getpwent_response);
}
}
-
+ done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
return ret;
}
@@ -415,6 +487,10 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
struct winbindd_request request;
static int keep_response=0;
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid);
+#endif
+
/* If our static buffer needs to be expanded we are called again */
if (!keep_response) {
@@ -434,7 +510,7 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
}
@@ -447,7 +523,7 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
keep_response = False;
@@ -455,11 +531,16 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
}
free_response(&response);
+ done:
+
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
+ (unsigned int)uid, nss_err_str(ret), ret);
+#endif
return ret;
}
/* Return passwd struct from username */
-
NSS_STATUS
_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
size_t buflen, int *errnop)
@@ -496,7 +577,7 @@ _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
}
@@ -509,7 +590,7 @@ _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
keep_response = False;
@@ -517,6 +598,11 @@ _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
}
free_response(&response);
+ done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
+ name, nss_err_str(ret), ret);
+#endif
return ret;
}
@@ -534,6 +620,7 @@ static int num_gr_cache; /* Current size of grp cache */
NSS_STATUS
_nss_winbind_setgrent(void)
{
+ NSS_STATUS ret;
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: setgrent\n", getpid());
#endif
@@ -543,7 +630,12 @@ _nss_winbind_setgrent(void)
free_response(&getgrent_response);
}
- return winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);
+ ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
+ return ret;
}
/* Close "file pointer" for ntdom group database */
@@ -551,6 +643,7 @@ _nss_winbind_setgrent(void)
NSS_STATUS
_nss_winbind_endgrent(void)
{
+ NSS_STATUS ret;
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: endgrent\n", getpid());
#endif
@@ -560,7 +653,12 @@ _nss_winbind_endgrent(void)
free_response(&getgrent_response);
}
- return winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);
+ ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
+ return ret;
}
/* Get next entry from ntdom group database */
@@ -613,12 +711,14 @@ winbind_getgrent(enum winbindd_cmd cmd,
return_result:
- gr_cache = getgrent_response.extra_data.data;
+ gr_cache = (struct winbindd_gr *)
+ getgrent_response.extra_data.data;
/* Check data is valid */
if (gr_cache == NULL) {
- return NSS_STATUS_NOTFOUND;
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
}
/* Fill group membership. The offset into the extra data
@@ -637,7 +737,7 @@ winbind_getgrent(enum winbindd_cmd cmd,
if (ret == NSS_STATUS_TRYAGAIN) {
called_again = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
*errnop = 0;
@@ -651,7 +751,11 @@ winbind_getgrent(enum winbindd_cmd cmd,
free_response(&getgrent_response);
}
}
-
+ done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(),
+ nss_err_str(ret), ret);
+#endif
return ret;
}
@@ -704,13 +808,13 @@ _nss_winbind_getgrnam_r(const char *name,
if (ret == NSS_STATUS_SUCCESS) {
ret = fill_grent(result, &response.data.gr,
- response.extra_data.data,
+ (char *)response.extra_data.data,
&buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
}
@@ -719,12 +823,13 @@ _nss_winbind_getgrnam_r(const char *name,
/* We've been called again */
ret = fill_grent(result, &response.data.gr,
- response.extra_data.data, &buffer, &buflen);
+ (char *)response.extra_data.data, &buffer,
+ &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
keep_response = False;
@@ -732,6 +837,11 @@ _nss_winbind_getgrnam_r(const char *name,
}
free_response(&response);
+ done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
+ name, nss_err_str(ret), ret);
+#endif
return ret;
}
@@ -767,13 +877,13 @@ _nss_winbind_getgrgid_r(gid_t gid,
if (ret == NSS_STATUS_SUCCESS) {
ret = fill_grent(result, &response.data.gr,
- response.extra_data.data,
+ (char *)response.extra_data.data,
&buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
}
@@ -782,12 +892,13 @@ _nss_winbind_getgrgid_r(gid_t gid,
/* We've been called again */
ret = fill_grent(result, &response.data.gr,
- response.extra_data.data, &buffer, &buflen);
+ (char *)response.extra_data.data, &buffer,
+ &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
*errnop = errno = ERANGE;
- return ret;
+ goto done;
}
keep_response = False;
@@ -795,6 +906,11 @@ _nss_winbind_getgrgid_r(gid_t gid,
}
free_response(&response);
+ done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
+ (unsigned int)gid, nss_err_str(ret), ret);
+#endif
return ret;
}
@@ -827,10 +943,26 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
int num_gids = response.data.num_entries;
gid_t *gid_list = (gid_t *)response.extra_data.data;
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
+ "and %d gids\n", getpid(),
+ user, num_gids);
+#endif
+ if (gid_list == NULL) {
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
+ }
+
/* Copy group list to client */
for (i = 0; i < num_gids; i++) {
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: initgroups %s (%d): "
+ "processing gid %d \n", getpid(),
+ user, group, gid_list[i]);
+#endif
+
/* Skip primary group */
if (gid_list[i] == group) {
@@ -853,7 +985,9 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
}
}
- newgroups = realloc((*groups), newsize * sizeof(**groups));
+ newgroups = (gid_t *)
+ realloc((*groups),
+ newsize * sizeof(**groups));
if (!newgroups) {
*errnop = ENOMEM;
ret = NSS_STATUS_NOTFOUND;
@@ -873,6 +1007,10 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
/* Back to your regularly scheduled programming */
done:
+#ifdef DEBUG_NSS
+ fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
+ user, nss_err_str(ret), ret);
+#endif
return ret;
}
diff --git a/source/nsswitch/winbind_nss_netbsd.c b/source/nsswitch/winbind_nss_netbsd.c
new file mode 100644
index 00000000000..97eb0cc76d4
--- /dev/null
+++ b/source/nsswitch/winbind_nss_netbsd.c
@@ -0,0 +1,405 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ NetBSD loadable authentication module, providing identification
+ routines against Samba winbind/Windows NT Domain
+
+ Copyright (C) Luke Mewburn 2004-2005
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <sys/param.h>
+
+#include "winbind_client.h"
+
+#include <stdarg.h>
+#include <syslog.h>
+
+ /* dynamic nsswitch with "new" getpw* nsdispatch API available */
+#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R)
+
+/*
+ group functions
+ ---------------
+*/
+
+static struct group _winbind_group;
+static char _winbind_groupbuf[1024];
+
+int
+netbsdwinbind_endgrent(void *nsrv, void *nscb, va_list ap)
+{
+ int rv;
+
+ rv = _nss_winbind_endgrent();
+ return rv;
+}
+
+int
+netbsdwinbind_setgrent(void *nsrv, void *nscb, va_list ap)
+{
+ int rv;
+
+ rv = _nss_winbind_setgrent();
+ return rv;
+}
+
+int
+netbsdwinbind_getgrent(void *nsrv, void *nscb, va_list ap)
+{
+ struct group **retval = va_arg(ap, struct group **);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+ rv = _nss_winbind_getgrent_r(&_winbind_group,
+ _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_group;
+ return rv;
+}
+
+int
+netbsdwinbind_getgrent_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ struct group *grp = va_arg(ap, struct group *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct group **result = va_arg(ap, struct group **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getgrent_r(grp, buffer, buflen, rerrno);
+ if (rv == NS_SUCCESS)
+ *result = grp;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+int
+netbsdwinbind_getgrgid(void *nsrv, void *nscb, va_list ap)
+{
+ struct group **retval = va_arg(ap, struct group **);
+ gid_t gid = va_arg(ap, gid_t);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+ rv = _nss_winbind_getgrgid_r(gid, &_winbind_group,
+ _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_group;
+ return rv;
+}
+
+int
+netbsdwinbind_getgrgid_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ gid_t gid = va_arg(ap, gid_t);
+ struct group *grp = va_arg(ap, struct group *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct group **result = va_arg(ap, struct group **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getgrgid_r(gid, grp, buffer, buflen, &rerrno);
+ if (rv == NS_SUCCESS)
+ *result = grp;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+int
+netbsdwinbind_getgrnam(void *nsrv, void *nscb, va_list ap)
+{
+ struct group **retval = va_arg(ap, struct group **);
+ const char *name = va_arg(ap, const char *);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+ rv = _nss_winbind_getgrnam_r(name, &_winbind_group,
+ _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_group;
+ return rv;
+}
+
+int
+netbsdwinbind_getgrnam_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ const char *name = va_arg(ap, const char *);
+ struct group *grp = va_arg(ap, struct group *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct group **result = va_arg(ap, struct group **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getgrnam_r(name, grp, buffer, buflen, &rerrno);
+ if (rv == NS_SUCCESS)
+ *result = grp;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+int
+netbsdwinbind_getgroupmembership(void *nsrv, void *nscb, va_list ap)
+{
+ int *result = va_arg(ap, int *);
+ const char *uname = va_arg(ap, const char *);
+ gid_t agroup = va_arg(ap, gid_t);
+ gid_t *groups = va_arg(ap, gid_t *);
+ int maxgrp = va_arg(ap, int);
+ int *groupc = va_arg(ap, int *);
+
+ struct winbindd_request request;
+ struct winbindd_response response;
+ gid_t *wblistv;
+ int wblistc, i, isdup, dupc;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+ strncpy(request.data.username, uname,
+ sizeof(request.data.username) - 1);
+ i = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
+ if (i != NSS_STATUS_SUCCESS)
+ return NS_NOTFOUND;
+ wblistv = (gid_t *)response.extra_data.data;
+ wblistc = response.data.num_entries;
+
+ for (i = 0; i < wblistc; i++) { /* add winbind gids */
+ isdup = 0; /* skip duplicates */
+ for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
+ if (groups[dupc] == wblistv[i]) {
+ isdup = 1;
+ break;
+ }
+ }
+ if (isdup)
+ continue;
+ if (*groupc < maxgrp) /* add this gid */
+ groups[*groupc] = wblistv[i];
+ else
+ *result = -1;
+ (*groupc)++;
+ }
+ SAFE_FREE(wblistv);
+ return NS_NOTFOUND;
+}
+
+
+/*
+ passwd functions
+ ----------------
+*/
+
+static struct passwd _winbind_passwd;
+static char _winbind_passwdbuf[1024];
+
+int
+netbsdwinbind_endpwent(void *nsrv, void *nscb, va_list ap)
+{
+ int rv;
+
+ rv = _nss_winbind_endpwent();
+ return rv;
+}
+
+int
+netbsdwinbind_setpwent(void *nsrv, void *nscb, va_list ap)
+{
+ int rv;
+
+ rv = _nss_winbind_setpwent();
+ return rv;
+}
+
+int
+netbsdwinbind_getpwent(void *nsrv, void *nscb, va_list ap)
+{
+ struct passwd **retval = va_arg(ap, struct passwd **);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+
+ rv = _nss_winbind_getpwent_r(&_winbind_passwd,
+ _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_passwd;
+ return rv;
+}
+
+int
+netbsdwinbind_getpwent_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ struct passwd *pw = va_arg(ap, struct passwd *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct passwd **result = va_arg(ap, struct passwd **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getpwent_r(pw, buffer, buflen, rerrno);
+ if (rv == NS_SUCCESS)
+ *result = pw;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+int
+netbsdwinbind_getpwnam(void *nsrv, void *nscb, va_list ap)
+{
+ struct passwd **retval = va_arg(ap, struct passwd **);
+ const char *name = va_arg(ap, const char *);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+ rv = _nss_winbind_getpwnam_r(name, &_winbind_passwd,
+ _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_passwd;
+ return rv;
+}
+
+int
+netbsdwinbind_getpwnam_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ const char *name = va_arg(ap, const char *);
+ struct passwd *pw = va_arg(ap, struct passwd *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct passwd **result = va_arg(ap, struct passwd **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getpwnam_r(name, pw, buffer, buflen, &rerrno);
+ if (rv == NS_SUCCESS)
+ *result = pw;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+int
+netbsdwinbind_getpwuid(void *nsrv, void *nscb, va_list ap)
+{
+ struct passwd **retval = va_arg(ap, struct passwd **);
+ uid_t uid = va_arg(ap, uid_t);
+
+ int rv, rerrno;
+
+ *retval = NULL;
+ rv = _nss_winbind_getpwuid_r(uid, &_winbind_passwd,
+ _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
+ if (rv == NS_SUCCESS)
+ *retval = &_winbind_passwd;
+ return rv;
+}
+
+int
+netbsdwinbind_getpwuid_r(void *nsrv, void *nscb, va_list ap)
+{
+ int *retval = va_arg(ap, int *);
+ uid_t uid = va_arg(ap, uid_t);
+ struct passwd *pw = va_arg(ap, struct passwd *);
+ char *buffer = va_arg(ap, char *);
+ size_t buflen = va_arg(ap, size_t);
+ struct passwd **result = va_arg(ap, struct passwd **);
+
+ int rv, rerrno;
+
+ *result = NULL;
+ rerrno = 0;
+
+ rv = _nss_winbind_getpwuid_r(uid, pw, buffer, buflen, &rerrno);
+ if (rv == NS_SUCCESS)
+ *result = pw;
+ else
+ *retval = rerrno;
+ return rv;
+}
+
+
+/*
+ nsswitch module setup
+ ---------------------
+*/
+
+
+static ns_mtab winbind_methods[] = {
+
+{ NSDB_GROUP, "endgrent", netbsdwinbind_endgrent, NULL },
+{ NSDB_GROUP, "getgrent", netbsdwinbind_getgrent, NULL },
+{ NSDB_GROUP, "getgrent_r", netbsdwinbind_getgrent_r, NULL },
+{ NSDB_GROUP, "getgrgid", netbsdwinbind_getgrgid, NULL },
+{ NSDB_GROUP, "getgrgid_r", netbsdwinbind_getgrgid_r, NULL },
+{ NSDB_GROUP, "getgrnam", netbsdwinbind_getgrnam, NULL },
+{ NSDB_GROUP, "getgrnam_r", netbsdwinbind_getgrnam_r, NULL },
+{ NSDB_GROUP, "setgrent", netbsdwinbind_setgrent, NULL },
+{ NSDB_GROUP, "setgroupent", netbsdwinbind_setgrent, NULL },
+{ NSDB_GROUP, "getgroupmembership", netbsdwinbind_getgroupmembership, NULL },
+
+{ NSDB_PASSWD, "endpwent", netbsdwinbind_endpwent, NULL },
+{ NSDB_PASSWD, "getpwent", netbsdwinbind_getpwent, NULL },
+{ NSDB_PASSWD, "getpwent_r", netbsdwinbind_getpwent_r, NULL },
+{ NSDB_PASSWD, "getpwnam", netbsdwinbind_getpwnam, NULL },
+{ NSDB_PASSWD, "getpwnam_r", netbsdwinbind_getpwnam_r, NULL },
+{ NSDB_PASSWD, "getpwuid", netbsdwinbind_getpwuid, NULL },
+{ NSDB_PASSWD, "getpwuid_r", netbsdwinbind_getpwuid_r, NULL },
+{ NSDB_PASSWD, "setpassent", netbsdwinbind_setpwent, NULL },
+{ NSDB_PASSWD, "setpwent", netbsdwinbind_setpwent, NULL },
+
+};
+
+ns_mtab *
+nss_module_register(const char *source, unsigned int *mtabsize,
+ nss_module_unregister_fn *unreg)
+{
+ *mtabsize = sizeof(winbind_methods)/sizeof(winbind_methods[0]);
+ *unreg = NULL;
+ return (winbind_methods);
+}
+
+#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */
diff --git a/source/nsswitch/winbind_nss_netbsd.h b/source/nsswitch/winbind_nss_netbsd.h
new file mode 100644
index 00000000000..e7f89bc1db9
--- /dev/null
+++ b/source/nsswitch/winbind_nss_netbsd.h
@@ -0,0 +1,42 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ NetBSD loadable authentication module, providing identification
+ routines against Samba winbind/Windows NT Domain
+
+ Copyright (C) Luke Mewburn 2004-2005
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _WINBIND_NSS_NETBSD_H
+#define _WINBIND_NSS_NETBSD_H
+
+#include <nsswitch.h>
+
+ /* dynamic nsswitch with "new" getpw* nsdispatch API available */
+#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R)
+
+typedef int NSS_STATUS;
+
+#define NSS_STATUS_SUCCESS NS_SUCCESS
+#define NSS_STATUS_NOTFOUND NS_NOTFOUND
+#define NSS_STATUS_UNAVAIL NS_UNAVAIL
+#define NSS_STATUS_TRYAGAIN NS_TRYAGAIN
+
+#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */
+
+#endif /* _WINBIND_NSS_NETBSD_H */
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 134fdde8882..b4570f2525a 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -34,6 +34,16 @@ static BOOL interactive = False;
extern BOOL override_logfile;
+struct event_context *winbind_event_context(void)
+{
+ static struct event_context *ctx;
+
+ if (!ctx && !(ctx = event_context_init(NULL))) {
+ smb_panic("Could not init winbind event context\n");
+ }
+ return ctx;
+}
+
/* Reload configuration */
static BOOL reload_services_file(void)
@@ -65,9 +75,7 @@ static BOOL reload_services_file(void)
static void fault_quit(void)
{
-#if DUMP_CORE
dump_core();
-#endif
}
static void winbindd_status(void)
@@ -113,13 +121,15 @@ static void terminate(void)
{
pstring path;
- idmap_close();
-
/* Remove socket file */
pstr_sprintf(path, "%s/%s",
WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
unlink(path);
+ idmap_close();
+
+ trustdom_cache_shutdown();
+
#if 0
if (interactive) {
TALLOC_CTX *mem_ctx = talloc_init("end_description");
@@ -166,7 +176,8 @@ static void sigchld_handler(int signum)
}
/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
-static void msg_reload_services(int msg_type, struct process_id src, void *buf, size_t len)
+static void msg_reload_services(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
/* Flush various caches */
flush_caches();
@@ -174,7 +185,8 @@ static void msg_reload_services(int msg_type, struct process_id src, void *buf,
}
/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
-static void msg_shutdown(int msg_type, struct process_id src, void *buf, size_t len)
+static void msg_shutdown(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
do_sigterm = True;
}
@@ -214,6 +226,7 @@ static struct winbindd_dispatch_table {
{ WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
{ WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" },
+ { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, winbindd_pam_chng_pswd_auth_crap, "CHNG_PSWD_AUTH_CRAP" },
/* Enumeration functions */
@@ -227,6 +240,7 @@ static struct winbindd_dispatch_table {
{ WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" },
{ WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" },
+ { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" },
/* Lookup related functions */
@@ -234,11 +248,16 @@ static struct winbindd_dispatch_table {
{ WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
{ WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
{ WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
+ { WINBINDD_SIDS_TO_XIDS, winbindd_sids_to_unixids, "SIDS_TO_XIDS" },
{ WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
{ WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" },
+ { WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" },
+ { WINBINDD_SET_HWM, winbindd_set_hwm, "SET_HWMS" },
/* Miscellaneous */
+ { WINBINDD_DUMP_MAPS, winbindd_dump_maps, "DUMP_MAPS" },
+
{ WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" },
{ WINBINDD_PING, winbindd_ping, "PING" },
{ WINBINDD_INFO, winbindd_info, "INFO" },
@@ -251,6 +270,9 @@ static struct winbindd_dispatch_table {
"WINBINDD_PRIV_PIPE_DIR" },
{ WINBINDD_GETDCNAME, winbindd_getdcname, "GETDCNAME" },
+ /* Credential cache access */
+ { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
+
/* WINS functions */
{ WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
@@ -602,8 +624,10 @@ static void new_connection(int listen_sock, BOOL privileged)
/* Create new connection structure */
- if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL)
+ if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL) {
+ close(sock);
return;
+ }
state->sock = sock;
@@ -629,37 +653,37 @@ static void remove_client(struct winbindd_cli_state *state)
{
/* It's a dead client - hold a funeral */
- if (state != NULL) {
+ if (state == NULL) {
+ return;
+ }
- /* Close socket */
+ /* Close socket */
- close(state->sock);
+ close(state->sock);
- /* Free any getent state */
+ /* Free any getent state */
- free_getent_state(state->getpwent_state);
- free_getent_state(state->getgrent_state);
+ free_getent_state(state->getpwent_state);
+ free_getent_state(state->getgrent_state);
- /* We may have some extra data that was not freed if the
- client was killed unexpectedly */
+ /* We may have some extra data that was not freed if the client was
+ killed unexpectedly */
- SAFE_FREE(state->response.extra_data.data);
+ SAFE_FREE(state->response.extra_data.data);
- if (state->mem_ctx != NULL) {
- talloc_destroy(state->mem_ctx);
- state->mem_ctx = NULL;
- }
+ if (state->mem_ctx != NULL) {
+ talloc_destroy(state->mem_ctx);
+ state->mem_ctx = NULL;
+ }
- remove_fd_event(&state->fd_event);
+ remove_fd_event(&state->fd_event);
- /* Remove from list and free */
+ /* Remove from list and free */
- winbindd_remove_client(state);
- TALLOC_FREE(state);
- }
+ winbindd_remove_client(state);
+ TALLOC_FREE(state);
}
-
/* Shutdown client connection which has been idle for the longest time */
static BOOL remove_idle_client(void)
@@ -700,7 +724,7 @@ static void process_loop(void)
struct fd_event *ev;
fd_set r_fds, w_fds;
int maxfd, listen_sock, listen_priv_sock, selret;
- struct timeval timeout;
+ struct timeval timeout, ev_timeout;
/* We'll be doing this a lot */
@@ -708,8 +732,10 @@ static void process_loop(void)
message_dispatch();
+ run_events(winbind_event_context(), 0, NULL, NULL);
+
/* refresh the trusted domain cache */
-
+
rescan_trusted_domains();
/* Free up temporary memory */
@@ -737,6 +763,11 @@ static void process_loop(void)
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
timeout.tv_usec = 0;
+ /* Check for any event timeouts. */
+ if (get_timed_events_timeout(winbind_event_context(), &ev_timeout)) {
+ timeout = timeval_min(&timeout, &ev_timeout);
+ }
+
/* Set up client readers and writers */
state = winbindd_client_list();
@@ -852,7 +883,7 @@ static void process_loop(void)
DEBUG(3, ("got SIGHUP\n"));
- msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0);
+ msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0, NULL);
do_sighup = False;
}
@@ -874,9 +905,7 @@ static void process_loop(void)
/* Main function */
-struct winbindd_state server_state; /* Server state information */
-
-int main(int argc, char **argv)
+int main(int argc, char **argv, char **envp)
{
pstring logfile;
static BOOL Fork = True;
@@ -950,14 +979,19 @@ int main(int argc, char **argv)
setup_logging("winbindd", log_stdout);
reopen_logs();
- DEBUG(1, ("winbindd version %s started.\n", SAMBA_VERSION_STRING) );
- DEBUGADD( 1, ( "Copyright The Samba Team 2000-2004\n" ) );
+ DEBUG(1, ("winbindd version %s started.\n%s\n",
+ SAMBA_VERSION_STRING,
+ COPYRIGHT_STARTUP_MESSAGE) );
if (!reload_services_file()) {
DEBUG(0, ("error opening config file\n"));
exit(1);
}
+ if (!directory_exist(lp_lockdir(), NULL)) {
+ mkdir(lp_lockdir(), 0755);
+ }
+
/* Setup names. */
if (!init_names())
@@ -975,18 +1009,16 @@ int main(int argc, char **argv)
namecache_enable();
- /* Check winbindd parameters are valid */
-
- ZERO_STRUCT(server_state);
-
/* Winbind daemon initialisation */
- if ( (!winbindd_param_init()) || (!winbindd_upgrade_idmap()) ||
- (!idmap_init(lp_idmap_backend())) ) {
- DEBUG(1, ("Could not init idmap -- netlogon proxy only\n"));
- idmap_set_proxyonly();
+ if ( ! NT_STATUS_IS_OK(idmap_init()) ) {
+ DEBUG(1, ("Could not init idmap! - Sid/[UG]id mapping will not be available\n"));
}
+#ifdef WITH_ADS
+ nss_init( lp_winbind_nss_info() );
+#endif
+
/* Unblock all signals we are interested in as they may have been
blocked by the parent process. */
@@ -1035,13 +1067,14 @@ int main(int argc, char **argv)
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
- message_register(MSG_SMB_CONF_UPDATED, msg_reload_services);
- message_register(MSG_SHUTDOWN, msg_shutdown);
+ message_register(MSG_SMB_CONF_UPDATED, msg_reload_services, NULL);
+ message_register(MSG_SHUTDOWN, msg_shutdown, NULL);
/* Handle online/offline messages. */
- message_register(MSG_WINBIND_OFFLINE,winbind_msg_offline);
- message_register(MSG_WINBIND_ONLINE,winbind_msg_online);
- message_register(MSG_WINBIND_ONLINESTATUS,winbind_msg_onlinestatus);
+ message_register(MSG_WINBIND_OFFLINE, winbind_msg_offline, NULL);
+ message_register(MSG_WINBIND_ONLINE, winbind_msg_online, NULL);
+ message_register(MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus,
+ NULL);
poptFreeContext(pc);
@@ -1062,7 +1095,5 @@ int main(int argc, char **argv)
while (1)
process_loop();
- trustdom_cache_shutdown();
-
return 0;
}
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 7d5330dccb2..b9e07a2321b 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -60,7 +60,7 @@ struct sid_ctr {
BOOL finished;
const char *domain;
const char *name;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
};
struct winbindd_cli_state {
@@ -107,21 +107,13 @@ struct getpwent_user {
/* Server state structure */
-struct winbindd_state {
-
- /* User and group id pool */
-
- uid_t uid_low, uid_high; /* Range of uids to allocate */
- gid_t gid_low, gid_high; /* Range of gids to allocate */
-};
-
-extern struct winbindd_state server_state; /* Server information */
-
typedef struct {
char *acct_name;
char *full_name;
char *homedir;
char *shell;
+ gid_t primary_gid; /* allow the nss_info
+ backend to set the primary group */
DOM_SID user_sid; /* NT user and primary group SIDs */
DOM_SID group_sid;
} WINBIND_USERINFO;
@@ -151,7 +143,6 @@ struct winbindd_child {
struct winbindd_domain *domain;
pstring logfilename;
- TALLOC_CTX *mem_ctx;
struct fd_event event;
struct timed_event *lockout_policy_event;
struct winbindd_async_request *requests;
@@ -162,6 +153,7 @@ struct winbindd_child {
struct winbindd_domain {
fstring name; /* Domain name */
fstring alt_name; /* alt Domain name (if any) */
+ fstring forest_name; /* Name of the AD forest we're in */
DOM_SID sid; /* SID for this domain */
BOOL initialized; /* Did we already ask for the domain mode? */
BOOL native_mode; /* is this a win2k domain in native mode ? */
@@ -169,6 +161,8 @@ struct winbindd_domain {
BOOL primary; /* is this our primary domain ? */
BOOL internal; /* BUILTIN and member SAM */
BOOL online; /* is this domain available ? */
+ time_t startup_time; /* When we set "startup" true. */
+ BOOL startup; /* are we in the first 30 seconds after startup_time ? */
/* Lookup methods for this domain (LDAP or RPC) */
struct winbindd_methods *methods;
@@ -199,6 +193,11 @@ struct winbindd_domain {
struct winbindd_child child;
+ /* Callback we use to try put us back online. */
+
+ uint32 check_online_timeout;
+ struct timed_event *check_online_event;
+
/* Linked list info */
struct winbindd_domain *prev, *next;
@@ -235,7 +234,7 @@ struct winbindd_methods {
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type);
+ enum lsa_SidType *type);
/* convert a sid to a user or group name */
NTSTATUS (*sid_to_name)(struct winbindd_domain *domain,
@@ -243,7 +242,16 @@ struct winbindd_methods {
const DOM_SID *sid,
char **domain_name,
char **name,
- enum SID_NAME_USE *type);
+ enum lsa_SidType *type);
+
+ NTSTATUS (*rids_to_names)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ uint32 *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types);
/* lookup user info for a given SID */
NTSTATUS (*query_user)(struct winbindd_domain *domain,
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 250b5f3b8c2..ea6dc2870a0 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -30,6 +30,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+extern struct winbindd_methods reconnect_methods;
+
/*
return our ads connections structure for a domain. We keep the connection
open to make things faster
@@ -38,22 +40,27 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
{
ADS_STRUCT *ads;
ADS_STATUS status;
- enum wb_posix_mapping map_type;
DEBUG(10,("ads_cached_connection\n"));
if (domain->private_data) {
- ads = (ADS_STRUCT *)domain->private_data;
+
+ time_t expire;
+ time_t now = time(NULL);
/* check for a valid structure */
+ ads = (ADS_STRUCT *)domain->private_data;
- DEBUG(7, ("Current tickets expire at %d, time is now %d\n",
- (uint32) ads->auth.expire, (uint32) time(NULL)));
- if ( ads->config.realm && (ads->auth.expire > time(NULL))) {
+ expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
+
+ DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
+ (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
+
+ if ( ads->config.realm && (expire > now)) {
return ads;
- }
- else {
+ } else {
/* we own this ADS_STRUCT so make sure it goes away */
+ DEBUG(7,("Deleting expired krb5 credential cache\n"));
ads->is_mine = True;
ads_destroy( &ads );
ads_kdestroy("MEMORY:winbind_ccache");
@@ -109,7 +116,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
status = ads_connect(ads);
if (!ADS_ERR_OK(status) || !ads->config.realm) {
- extern struct winbindd_methods msrpc_methods, cache_methods;
DEBUG(1,("ads_connect for domain %s failed: %s\n",
domain->name, ads_errstr(status)));
ads_destroy(&ads);
@@ -118,28 +124,13 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
server, fall back to MSRPC */
if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
status.err.rc == ECONNREFUSED) {
+ /* 'reconnect_methods' is the MS-RPC backend. */
DEBUG(1,("Trying MSRPC methods\n"));
- if (domain->methods == &cache_methods) {
- domain->backend = &msrpc_methods;
- } else {
- domain->methods = &msrpc_methods;
- }
+ domain->backend = &reconnect_methods;
}
return NULL;
}
- map_type = get_nss_info(domain->name);
-
- if ((map_type == WB_POSIX_MAP_RFC2307)||
- (map_type == WB_POSIX_MAP_SFU)) {
-
- status = ads_check_posix_schema_mapping(ads, map_type);
- if (!ADS_ERR_OK(status)) {
- DEBUG(10,("ads_check_posix_schema_mapping failed "
- "with: %s\n", ads_errstr(status)));
- }
- }
-
/* set the flag that says we don't own the memory even
though we do so that ads_destroy() won't destroy the
structure we pass back by reference */
@@ -158,21 +149,11 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
WINBIND_USERINFO **info)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"userPrincipalName",
- "sAMAccountName",
- "name", "objectSid", "primaryGroupID",
- "sAMAccountType",
- ADS_ATTR_SFU_HOMEDIR_OID,
- ADS_ATTR_SFU_SHELL_OID,
- ADS_ATTR_SFU_GECOS_OID,
- ADS_ATTR_RFC2307_HOMEDIR_OID,
- ADS_ATTR_RFC2307_SHELL_OID,
- ADS_ATTR_RFC2307_GECOS_OID,
- NULL};
+ const char *attrs[] = { "*", NULL };
int i, count;
ADS_STATUS rc;
- void *res = NULL;
- void *msg = NULL;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
*num_entries = 0;
@@ -212,6 +193,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
char *shell = NULL;
uint32 group;
uint32 atype;
+ DOM_SID user_sid;
+ gid_t primary_gid = (gid_t)-1;
if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
ads_atype_map(atype) != SID_NAME_USER) {
@@ -221,17 +204,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
name = ads_pull_username(ads, mem_ctx, msg);
- if (get_nss_info(domain->name) && ads->schema.map_type) {
-
- DEBUG(10,("pulling posix attributes (%s schema)\n",
- wb_posix_map_str(ads->schema.map_type)));
-
- homedir = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_homedir_attr);
- shell = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_shell_attr);
- gecos = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_gecos_attr);
+ if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
+ status = nss_get_info( domain->name, &user_sid, mem_ctx,
+ ads, msg, &homedir, &shell, &gecos,
+ &primary_gid );
}
if (gecos == NULL) {
@@ -252,6 +228,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
(*info)[i].full_name = gecos;
(*info)[i].homedir = homedir;
(*info)[i].shell = shell;
+ (*info)[i].primary_gid = primary_gid;
sid_compose(&(*info)[i].group_sid, &domain->sid, group);
i++;
}
@@ -279,8 +256,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
"name", "objectSid", NULL};
int i, count;
ADS_STATUS rc;
- void *res = NULL;
- void *msg = NULL;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
const char *filter;
BOOL enum_dom_local_groups = False;
@@ -413,7 +390,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
const char *dn,
char **name, uint32 *name_type, DOM_SID *sid)
{
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *attrs[] = {"userPrincipalName", "sAMAccountName",
"objectSid", "sAMAccountType", NULL};
ADS_STATUS rc;
@@ -456,20 +433,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
WINBIND_USERINFO *info)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"userPrincipalName",
- "sAMAccountName",
- "name",
- "primaryGroupID",
- ADS_ATTR_SFU_HOMEDIR_OID,
- ADS_ATTR_SFU_SHELL_OID,
- ADS_ATTR_SFU_GECOS_OID,
- ADS_ATTR_RFC2307_HOMEDIR_OID,
- ADS_ATTR_RFC2307_SHELL_OID,
- ADS_ATTR_RFC2307_GECOS_OID,
- NULL};
+ const char *attrs[] = { "*", NULL };
ADS_STATUS rc;
int count;
- void *msg = NULL;
+ LDAPMessage *msg = NULL;
char *ldap_exp;
char *sidstr;
uint32 group_rid;
@@ -477,9 +444,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
DEBUG(3,("ads: query_user\n"));
- ads = ads_cached_connection(domain);
-
- if (!ads) {
+ if ( (ads = ads_cached_connection(domain)) == NULL ) {
domain->last_status = NT_STATUS_SERVER_DISABLED;
goto done;
}
@@ -504,18 +469,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
- if (get_nss_info(domain->name) && ads->schema.map_type) {
-
- DEBUG(10,("pulling posix attributes (%s schema)\n",
- wb_posix_map_str(ads->schema.map_type)));
-
- info->homedir = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_homedir_attr);
- info->shell = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_shell_attr);
- info->full_name = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.posix_gecos_attr);
- }
+ info->primary_gid = (gid_t)-1;
+ nss_get_info( domain->name, sid, mem_ctx, ads, msg,
+ &info->homedir, &info->shell, &info->full_name, &info->primary_gid );
if (info->full_name == NULL) {
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
@@ -551,8 +507,8 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
int count;
- void *res = NULL;
- void *msg = NULL;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
char *ldap_exp;
ADS_STRUCT *ads;
const char *group_attrs[] = {"objectSid", NULL};
@@ -595,7 +551,10 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
num_groups = 0;
/* always add the primary group to the sid array */
- add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups);
+ if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
if (count > 0) {
for (msg = ads_first_entry(ads, res); msg;
@@ -612,8 +571,11 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
continue;
}
- add_sid_to_array(mem_ctx, &group_sid, user_sids,
- &num_groups);
+ if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
+ &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
}
@@ -640,11 +602,12 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
int count;
- void *res = NULL;
+ LDAPMessage *res = NULL;
ADS_STRUCT *ads;
const char *attrs[] = {"memberOf", NULL};
size_t num_groups = 0;
DOM_SID *group_sids = NULL;
+ char *escaped_dn;
int i;
DEBUG(3,("ads: lookup_usergroups_memberof\n"));
@@ -656,9 +619,16 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
goto done;
}
- rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs,
+ if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ rc = ads_search_retry_extended_dn(ads, &res, escaped_dn, attrs,
ADS_EXTENDED_DN_HEX_STRING);
+ SAFE_FREE(escaped_dn);
+
if (!ADS_ERR_OK(rc) || !res) {
DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n",
user_dn, ads_errstr(rc)));
@@ -676,7 +646,10 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
num_groups = 0;
/* always add the primary group to the sid array */
- add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups);
+ if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
count = ads_pull_sids_from_extendeddn(ads, mem_ctx, res, "memberOf",
ADS_EXTENDED_DN_HEX_STRING,
@@ -694,13 +667,16 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
continue;
}
- add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
- &num_groups);
+ if (!add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
+ &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
*p_num_groups = num_groups;
- status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+ status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n", user_dn));
done:
@@ -749,7 +725,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done;
}
- rc = ads_search_retry_sid(ads, (void**)(void *)&msg, sid, attrs);
+ rc = ads_search_retry_sid(ads, &msg, sid, attrs);
if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc);
@@ -825,7 +801,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
*user_sids = NULL;
num_groups = 0;
- add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups);
+ if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
for (i=0;i<count;i++) {
@@ -834,12 +813,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
continue;
}
- add_sid_to_array_unique(mem_ctx, &sids[i],
- user_sids, &num_groups);
+ if (!add_sid_to_array_unique(mem_ctx, &sids[i],
+ user_sids, &num_groups)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
*p_num_groups = (uint32)num_groups;
- status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+ status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
sid_to_string(sid_string, sid)));
@@ -860,7 +842,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
{
ADS_STATUS rc;
int count;
- void *res=NULL;
+ LDAPMessage *res=NULL;
ADS_STRUCT *ads = NULL;
char *ldap_exp;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@@ -1030,11 +1012,15 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
if (!ADS_ERR_OK(rc)) {
- /* its a dead connection ; don't destroy it
- through since ads_USN() has already done
- that indirectly */
-
- domain->private_data = NULL;
+ /* its a dead connection, destroy it */
+
+ if (domain->private_data) {
+ ads = (ADS_STRUCT *)domain->private_data;
+ ads->is_mine = True;
+ ads_destroy(&ads);
+ ads_kdestroy("MEMORY:winbind_ccache");
+ domain->private_data = NULL;
+ }
}
return ads_ntstatus(rc);
}
@@ -1119,6 +1105,7 @@ struct winbindd_methods ads_methods = {
enum_local_groups,
msrpc_name_to_sid,
msrpc_sid_to_name,
+ msrpc_rids_to_names,
query_user,
lookup_usergroups,
msrpc_lookup_useraliases,
diff --git a/source/nsswitch/winbindd_async.c b/source/nsswitch/winbindd_async.c
index 1656c03261c..cafaf1cb056 100644
--- a/source/nsswitch/winbindd_async.c
+++ b/source/nsswitch/winbindd_async.c
@@ -4,7 +4,7 @@
Async helpers for blocking functions
Copyright (C) Volker Lendecke 2005
- Copyright (C) Volker Lendecke 2006
+ Copyright (C) Gerald Carter 2006
The helpers always consist of three functions:
@@ -112,11 +112,11 @@ void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
&state->response, do_async_recv, state);
}
-static void idmap_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
+static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ) = c;
+ void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
if (!success) {
DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
@@ -133,30 +133,26 @@ static void idmap_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
cont(private_data, True);
}
-void idmap_set_mapping_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
- unid_t id, int id_type,
+void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map,
void (*cont)(void *private_data, BOOL success),
void *private_data)
{
struct winbindd_request request;
ZERO_STRUCT(request);
- request.cmd = WINBINDD_DUAL_IDMAPSET;
- if (id_type == ID_USERID)
- request.data.dual_idmapset.uid = id.uid;
- else
- request.data.dual_idmapset.gid = id.gid;
- request.data.dual_idmapset.type = id_type;
- sid_to_string(request.data.dual_idmapset.sid, sid);
-
- do_async(mem_ctx, idmap_child(), &request, idmap_set_mapping_recv,
- cont, private_data);
+ request.cmd = WINBINDD_DUAL_SET_MAPPING;
+ request.data.dual_idmapset.id = map->xid.id;
+ request.data.dual_idmapset.type = map->xid.type;
+ sid_to_string(request.data.dual_idmapset.sid, map->sid);
+
+ do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv,
+ (void *)cont, private_data);
}
-enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain,
+enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
+ struct id_map map;
DOM_SID sid;
- unid_t id;
NTSTATUS result;
DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
@@ -164,63 +160,176 @@ enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain,
if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
return WINBINDD_ERROR;
- if (state->request.data.dual_idmapset.type == ID_USERID)
- id.uid = state->request.data.dual_idmapset.uid;
- else
- id.gid = state->request.data.dual_idmapset.gid;
+ map.sid = &sid;
+ map.xid.id = state->request.data.dual_idmapset.id;
+ map.xid.type = state->request.data.dual_idmapset.type;
+
+ result = idmap_set_mapping(&map);
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+}
+
+static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success,
+ struct winbindd_response *response,
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
+
+ if (!success) {
+ DEBUG(5, ("Could not trigger idmap_set_hwm\n"));
+ cont(private_data, False);
+ return;
+ }
+
+ if (response->result != WINBINDD_OK) {
+ DEBUG(5, ("idmap_set_hwm returned an error\n"));
+ cont(private_data, False);
+ return;
+ }
+
+ cont(private_data, True);
+}
+
+void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid,
+ void (*cont)(void *private_data, BOOL success),
+ void *private_data)
+{
+ struct winbindd_request request;
+ ZERO_STRUCT(request);
+ request.cmd = WINBINDD_DUAL_SET_HWM;
+ request.data.dual_idmapset.id = xid->id;
+ request.data.dual_idmapset.type = xid->type;
+
+ do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv,
+ (void *)cont, private_data);
+}
+
+enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ struct unixid xid;
+ NTSTATUS result;
+
+ DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid));
+
+ xid.id = state->request.data.dual_idmapset.id;
+ xid.type = state->request.data.dual_idmapset.type;
- result = idmap_set_mapping(&sid, id,
- state->request.data.dual_idmapset.type);
+ switch (xid.type) {
+ case ID_TYPE_UID:
+ result = idmap_set_uid_hwm(&xid);
+ break;
+ case ID_TYPE_GID:
+ result = idmap_set_gid_hwm(&xid);
+ break;
+ default:
+ return WINBINDD_ERROR;
+ }
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
-static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
+static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
- void *c, void *private_data);
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, BOOL succ, void *, int) =
+ (void (*)(void *, BOOL, void *, int))c;
-void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
- void (*cont)(void *private_data, BOOL success, uid_t uid),
+ if (!success) {
+ DEBUG(5, ("Could not trigger sids2xids\n"));
+ cont(private_data, False, NULL, 0);
+ return;
+ }
+
+ if (response->result != WINBINDD_OK) {
+ DEBUG(5, ("sids2xids returned an error\n"));
+ cont(private_data, False, NULL, 0);
+ return;
+ }
+
+ cont(private_data, True, response->extra_data.data, response->length - sizeof(response));
+}
+
+void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size,
+ void (*cont)(void *private_data, BOOL success, void *data, int len),
void *private_data)
{
struct winbindd_request request;
ZERO_STRUCT(request);
- request.cmd = WINBINDD_DUAL_SID2UID;
- sid_to_string(request.data.dual_sid2id.sid, sid);
- request.data.dual_sid2id.alloc = alloc;
- do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv,
- cont, private_data);
+ request.cmd = WINBINDD_DUAL_SIDS2XIDS;
+ request.extra_data.data = (char *)sids;
+ request.extra_len = size;
+ do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv,
+ (void *)cont, private_data);
}
-enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
+enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- DOM_SID sid;
+ DOM_SID *sids;
+ struct unixid *xids;
+ struct id_map **ids;
NTSTATUS result;
+ int num, i;
- DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
- state->request.data.dual_sid2id.sid));
+ DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid));
- if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request.data.dual_sid2id.sid));
+ sids = (DOM_SID *)state->request.extra_data.data;
+ num = state->request.extra_len / sizeof(DOM_SID);
+
+ ids = talloc_zero_array(state->mem_ctx, struct id_map *, num + 1);
+ if ( ! ids) {
+ DEBUG(0, ("Out of memory!\n"));
return WINBINDD_ERROR;
}
+ for (i = 0; i < num; i++) {
+ ids[i] = talloc(ids, struct id_map);
+ if ( ! ids[i]) {
+ DEBUG(0, ("Out of memory!\n"));
+ talloc_free(ids);
+ return WINBINDD_ERROR;
+ }
+ ids[i]->sid = &sids[i];
+ }
- /* Find uid for this sid and return it, possibly ask the slow remote
- * idmap */
+ result = idmap_sids_to_unixids(ids);
- result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
- state->request.data.dual_sid2id.alloc ?
- 0 : ID_QUERY_ONLY);
+ if (NT_STATUS_IS_OK(result)) {
- return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+ xids = SMB_MALLOC_ARRAY(struct unixid, num);
+ if ( ! xids) {
+ DEBUG(0, ("Out of memory!\n"));
+ talloc_free(ids);
+ return WINBINDD_ERROR;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (ids[i]->status == ID_MAPPED) {
+ xids[i].type = ids[i]->xid.type;
+ xids[i].id = ids[i]->xid.id;
+ } else {
+ xids[i].type = -1;
+ }
+ }
+
+ state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num);
+ state->response.extra_data.data = xids;
+
+ } else {
+ DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result)));
+ talloc_free(ids);
+ return WINBINDD_ERROR;
+ }
+
+ talloc_free(ids);
+ return WINBINDD_OK;
}
-static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
+static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
+ void (*cont)(void *priv, BOOL succ, uid_t uid) =
+ (void (*)(void *, BOOL, uid_t))c;
if (!success) {
DEBUG(5, ("Could not trigger sid2uid\n"));
@@ -237,6 +346,41 @@ static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
cont(private_data, True, response->data.uid);
}
+void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ void (*cont)(void *private_data, BOOL success, uid_t uid),
+ void *private_data)
+{
+ struct winbindd_request request;
+ ZERO_STRUCT(request);
+ request.cmd = WINBINDD_DUAL_SID2UID;
+ sid_to_string(request.data.dual_sid2id.sid, sid);
+ do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv,
+ (void *)cont, private_data);
+}
+
+enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ DOM_SID sid;
+ NTSTATUS result;
+
+ DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
+ state->request.data.dual_sid2id.sid));
+
+ if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ state->request.data.dual_sid2id.sid));
+ return WINBINDD_ERROR;
+ }
+
+ /* Find uid for this sid and return it, possibly ask the slow remote idmap */
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid));
+
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+}
+
+#if 0 /* not used */
static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data);
@@ -251,8 +395,9 @@ void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
request.cmd = WINBINDD_DUAL_UID2NAME;
request.data.uid = uid;
do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
+#endif /* not used */
enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
@@ -273,11 +418,13 @@ enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
return WINBINDD_OK;
}
+#if 0 /* not used */
static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, const char *name) = c;
+ void (*cont)(void *priv, BOOL succ, const char *name) =
+ (void (*)(void *, BOOL, const char *))c;
if (!success) {
DEBUG(5, ("Could not trigger uid2name\n"));
@@ -308,8 +455,9 @@ static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
request.cmd = WINBINDD_DUAL_NAME2UID;
fstrcpy(request.data.username, name);
do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
+#endif /* not used */
enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
@@ -332,11 +480,13 @@ enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
return WINBINDD_OK;
}
+#if 0 /* not used */
static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
+ void (*cont)(void *priv, BOOL succ, uid_t uid) =
+ (void (*)(void *, BOOL, uid_t))c;
if (!success) {
DEBUG(5, ("Could not trigger name2uid\n"));
@@ -352,12 +502,31 @@ static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
cont(private_data, True, response->data.uid);
}
+#endif /* not used */
-static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
+static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
- void *c, void *private_data);
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, BOOL succ, gid_t gid) =
+ (void (*)(void *, BOOL, gid_t))c;
-void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
+ if (!success) {
+ DEBUG(5, ("Could not trigger sid2gid\n"));
+ cont(private_data, False, 0);
+ return;
+ }
+
+ if (response->result != WINBINDD_OK) {
+ DEBUG(5, ("sid2gid returned an error\n"));
+ cont(private_data, False, 0);
+ return;
+ }
+
+ cont(private_data, True, response->data.gid);
+}
+
+void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
void (*cont)(void *private_data, BOOL success, gid_t gid),
void *private_data)
{
@@ -369,9 +538,8 @@ void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
DEBUG(7,("idmap_sid2gid_async: Resolving %s to a gid\n",
request.data.dual_sid2id.sid));
- request.data.dual_sid2id.alloc = alloc;
- do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
- cont, private_data);
+ do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv,
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
@@ -389,51 +557,21 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
return WINBINDD_ERROR;
}
- /* Find gid for this sid and return it, possibly ask the slow remote
- * idmap */
-
- result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
- state->request.data.dual_sid2id.alloc ?
- 0 : ID_QUERY_ONLY);
+ /* Find gid for this sid and return it, possibly ask the slow remote idmap */
- /* If the lookup failed, the perhaps we need to look
- at the passdb for local groups */
-
- if ( !NT_STATUS_IS_OK(result) ) {
- if ( sid_to_gid( &sid, &(state->response.data.gid) ) ) {
- result = NT_STATUS_OK;
- }
- }
+ result = idmap_sid_to_gid(&sid, &state->response.data.gid);
+
+ DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid));
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
-static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
- struct winbindd_response *response,
- void *c, void *private_data)
-{
- void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
-
- if (!success) {
- DEBUG(5, ("Could not trigger sid2gid\n"));
- cont(private_data, False, 0);
- return;
- }
-
- if (response->result != WINBINDD_OK) {
- DEBUG(5, ("sid2gid returned an error\n"));
- cont(private_data, False, 0);
- return;
- }
-
- cont(private_data, True, response->data.gid);
-}
-
static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, const char *name) = c;
+ void (*cont)(void *priv, BOOL succ, const char *name) =
+ (void (*)(void *, BOOL, const char *))c;
if (!success) {
DEBUG(5, ("Could not trigger gid2name\n"));
@@ -460,7 +598,7 @@ void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
request.cmd = WINBINDD_DUAL_GID2NAME;
request.data.gid = gid;
do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
@@ -479,6 +617,7 @@ enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
return WINBINDD_OK;
}
+#if 0 /* not used */
static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data);
@@ -493,8 +632,9 @@ static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
request.cmd = WINBINDD_DUAL_NAME2GID;
fstrcpy(request.data.groupname, name);
do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
+#endif /* not used */
enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
@@ -517,11 +657,13 @@ enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
return WINBINDD_OK;
}
+#if 0 /* not used */
static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
+ void (*cont)(void *priv, BOOL succ, gid_t gid) =
+ (void (*)(void *, BOOL, gid_t))c;
if (!success) {
DEBUG(5, ("Could not trigger name2gid\n"));
@@ -537,14 +679,16 @@ static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
cont(private_data, True, response->data.gid);
}
-
+#endif /* not used */
static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ, const char *dom_name,
- const char *name, enum SID_NAME_USE type) = c;
+ const char *name, enum lsa_SidType type) =
+ (void (*)(void *, BOOL, const char *, const char *,
+ enum lsa_SidType))c;
if (!success) {
DEBUG(5, ("Could not trigger lookupsid\n"));
@@ -559,14 +703,15 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
}
cont(private_data, True, response->data.name.dom_name,
- response->data.name.name, response->data.name.type);
+ response->data.name.name,
+ (enum lsa_SidType)response->data.name.type);
}
void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
void (*cont)(void *private_data, BOOL success,
const char *dom_name,
const char *name,
- enum SID_NAME_USE type),
+ enum lsa_SidType type),
void *private_data)
{
struct winbindd_domain *domain;
@@ -585,16 +730,16 @@ void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
fstrcpy(request.data.sid, sid_string_static(sid));
do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
DOM_SID sid;
- fstring name;
- fstring dom_name;
+ char *name;
+ char *dom_name;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -611,8 +756,10 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
/* Lookup the sid */
- if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
+ if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, &dom_name, &name,
&type)) {
+ TALLOC_FREE(dom_name);
+ TALLOC_FREE(name);
return WINBINDD_ERROR;
}
@@ -620,15 +767,22 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
fstrcpy(state->response.data.name.name, name);
state->response.data.name.type = type;
+ TALLOC_FREE(dom_name);
+ TALLOC_FREE(name);
return WINBINDD_OK;
}
-static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
+/********************************************************************
+ This is the second callback after contacting the forest root
+********************************************************************/
+
+static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
- enum SID_NAME_USE type) = c;
+ enum lsa_SidType type) =
+ (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
DOM_SID sid;
if (!success) {
@@ -650,22 +804,84 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- cont(private_data, True, &sid, response->data.sid.type);
+ cont(private_data, True, &sid,
+ (enum lsa_SidType)response->data.sid.type);
+}
+
+/********************************************************************
+ This is the first callback after contacting our own domain
+********************************************************************/
+
+static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
+ struct winbindd_response *response,
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
+ enum lsa_SidType type) =
+ (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
+ DOM_SID sid;
+
+ if (!success) {
+ DEBUG(5, ("lookupname_recv: lookup_name() failed!\n"));
+ cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+ return;
+ }
+
+ if (response->result != WINBINDD_OK) {
+ /* Try again using the forest root */
+ struct winbindd_domain *root_domain = find_root_domain();
+ struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data;
+ struct winbindd_request request;
+ char *name_domain, *name_account;
+
+ if ( !root_domain ) {
+ DEBUG(5,("lookupname_recv: unable to determine forest root\n"));
+ cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+ return;
+ }
+
+ name_domain = state->request.data.name.dom_name;
+ name_account = state->request.data.name.name;
+
+ ZERO_STRUCT(request);
+ request.cmd = WINBINDD_LOOKUPNAME;
+ fstrcpy(request.data.name.dom_name, name_domain);
+ fstrcpy(request.data.name.name, name_account);
+
+ do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2,
+ (void *)cont, private_data);
+
+ return;
+ }
+
+ if (!string_to_sid(&sid, response->data.sid.sid)) {
+ DEBUG(0, ("Could not convert string %s to sid\n",
+ response->data.sid.sid));
+ cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+ return;
+ }
+
+ cont(private_data, True, &sid,
+ (enum lsa_SidType)response->data.sid.type);
}
-void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
- const char *name,
+/********************************************************************
+ The lookup name call first contacts a DC in its own domain
+ and fallbacks to contact a DC in the forest in our domain doesn't
+ know the name.
+********************************************************************/
+
+void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
+ const char *dom_name, const char *name,
void (*cont)(void *private_data, BOOL success,
const DOM_SID *sid,
- enum SID_NAME_USE type),
+ enum lsa_SidType type),
void *private_data)
{
struct winbindd_request request;
struct winbindd_domain *domain;
- domain = find_lookup_domain_from_name(dom_name);
-
- if (domain == NULL) {
+ if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) {
DEBUG(5, ("Could not find domain for name %s\n", dom_name));
cont(private_data, False, NULL, SID_NAME_UNKNOWN);
return;
@@ -677,22 +893,22 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
fstrcpy(request.data.name.name, name);
do_async_domain(mem_ctx, domain, &request, lookupname_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
char *name_domain, *name_user;
DOM_SID sid;
char *p;
/* Ensure null termination */
- state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
+ state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0';
/* Ensure null termination */
- state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
+ state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0';
/* cope with the name being a fully qualified name */
p = strstr(state->request.data.name.name, lp_winbind_separator());
@@ -708,7 +924,7 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
name_domain, lp_winbind_separator(), name_user));
- /* Lookup name from PDC using lsa_lookup_names() */
+ /* Lookup name from DC using lsa_lookup_names() */
if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
name_user, &sid, &type)) {
return WINBINDD_ERROR;
@@ -740,8 +956,8 @@ BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
return True;
}
-BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
- DOM_SID **sids, size_t *num_sids)
+static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
+ DOM_SID **sids, size_t *num_sids)
{
char *p, *q;
@@ -762,34 +978,16 @@ BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
DEBUG(0, ("Could not parse sid %s\n", p));
return False;
}
- add_sid_to_array(mem_ctx, &sid, sids, num_sids);
+ if (!add_sid_to_array(mem_ctx, &sid, sids, num_sids)) {
+ return False;
+ }
p = q;
}
return True;
}
-BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, size_t num_rids,
- char **result, ssize_t *len)
-{
- size_t i;
- size_t buflen = 0;
-
- *len = 0;
- *result = NULL;
- for (i=0; i<num_rids; i++) {
- sprintf_append(mem_ctx, result, len, &buflen,
- "%ld\n", rids[i]);
- }
-
- if ((num_rids != 0) && (*result == NULL)) {
- return False;
- }
-
- return True;
-}
-
-BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
- uint32 **sids, size_t *num_rids)
+static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
+ uint32 **rids, size_t *num_rids)
{
char *p;
@@ -806,17 +1004,79 @@ BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
return False;
}
p = q+1;
- ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids);
+ ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
}
return True;
}
+enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ uint32 *rids = NULL;
+ size_t i, buflen, num_rids = 0;
+ ssize_t len;
+ DOM_SID domain_sid;
+ char *domain_name;
+ char **names;
+ enum lsa_SidType *types;
+ NTSTATUS status;
+ char *result;
+
+ DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
+ state->request.domain_name,
+ state->request.data.sid));
+
+ if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
+ &rids, &num_rids)) {
+ DEBUG(5, ("Could not parse ridlist\n"));
+ return WINBINDD_ERROR;
+ }
+
+ if (!string_to_sid(&domain_sid, state->request.data.sid)) {
+ DEBUG(5, ("Could not parse domain sid %s\n",
+ state->request.data.sid));
+ return WINBINDD_ERROR;
+ }
+
+ status = domain->methods->rids_to_names(domain, state->mem_ctx,
+ &domain_sid, rids, num_rids,
+ &domain_name,
+ &names, &types);
+
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
+ return WINBINDD_ERROR;
+ }
+
+ len = 0;
+ buflen = 0;
+ result = NULL;
+
+ for (i=0; i<num_rids; i++) {
+ sprintf_append(state->mem_ctx, &result, &len, &buflen,
+ "%d %s\n", types[i], names[i]);
+ }
+
+ fstrcpy(state->response.data.domain_name, domain_name);
+
+ if (result != NULL) {
+ state->response.extra_data.data = SMB_STRDUP(result);
+ if (!state->response.extra_data.data) {
+ return WINBINDD_ERROR;
+ }
+ state->response.length += len+1;
+ }
+
+ return WINBINDD_OK;
+}
+
static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ,
- DOM_SID *aliases, size_t num_aliases) = c;
+ DOM_SID *aliases, size_t num_aliases) =
+ (void (*)(void *, BOOL, DOM_SID *, size_t))c;
char *aliases_str;
DOM_SID *sids = NULL;
size_t num_sids = 0;
@@ -833,7 +1093,7 @@ static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- aliases_str = response->extra_data.data;
+ aliases_str = (char *)response->extra_data.data;
if (aliases_str == NULL) {
DEBUG(10, ("getsidaliases return 0 SIDs\n"));
@@ -881,7 +1141,7 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain,
request.extra_data.data = sidstr;
do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
@@ -889,7 +1149,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
{
DOM_SID *sids = NULL;
size_t num_sids = 0;
- char *sidstr;
+ char *sidstr = NULL;
ssize_t len;
size_t i;
uint32 num_aliases;
@@ -899,8 +1159,13 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
sidstr = state->request.extra_data.data;
- if (sidstr == NULL)
+ if (sidstr == NULL) {
sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
+ if (!sidstr) {
+ DEBUG(0, ("Out of memory\n"));
+ return WINBINDD_ERROR;
+ }
+ }
DEBUG(10, ("Sidlist: %s\n", sidstr));
@@ -926,6 +1191,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
num_sids = 0;
sids = NULL;
+ sidstr = NULL;
DEBUG(10, ("Got %d aliases\n", num_aliases));
@@ -934,16 +1200,26 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
DEBUGADD(10, (" rid %d\n", alias_rids[i]));
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, alias_rids[i]);
- add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
+ if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) {
+ return WINBINDD_ERROR;
+ }
}
- if (!print_sidlist(NULL, sids, num_sids,
- (char **)&state->response.extra_data.data, &len)) {
+
+ if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
DEBUG(0, ("Could not print_sidlist\n"));
+ state->response.extra_data.data = NULL;
return WINBINDD_ERROR;
}
- if (state->response.extra_data.data != NULL) {
+ state->response.extra_data.data = NULL;
+
+ if (sidstr) {
+ state->response.extra_data.data = SMB_STRDUP(sidstr);
+ if (!state->response.extra_data.data) {
+ DEBUG(0, ("Out of memory\n"));
+ return WINBINDD_ERROR;
+ }
DEBUG(10, ("aliases_list: %s\n",
(char *)state->response.extra_data.data));
state->response.length += len+1;
@@ -1026,7 +1302,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- sids_str = response->extra_data.data;
+ sids_str = (char *)response->extra_data.data;
if (sids_str == NULL) {
/* This could be normal if we are dealing with a
@@ -1042,8 +1318,12 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
state->sids = NULL;
state->num_sids = 0;
- add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
- &state->num_sids);
+ if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
+ &state->num_sids)) {
+ DEBUG(0, ("Out of memory\n"));
+ state->cont(state->private_data, False, NULL, 0);
+ return;
+ }
if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
&state->num_sids)) {
@@ -1070,7 +1350,7 @@ static void gettoken_recvaliases(void *private_data, BOOL success,
const DOM_SID *aliases,
size_t num_aliases)
{
- struct gettoken_state *state = private_data;
+ struct gettoken_state *state = (struct gettoken_state *)private_data;
size_t i;
if (!success) {
@@ -1079,9 +1359,14 @@ static void gettoken_recvaliases(void *private_data, BOOL success,
return;
}
- for (i=0; i<num_aliases; i++)
- add_sid_to_array(state->mem_ctx, &aliases[i],
- &state->sids, &state->num_sids);
+ for (i=0; i<num_aliases; i++) {
+ if (!add_sid_to_array(state->mem_ctx, &aliases[i],
+ &state->sids, &state->num_sids)) {
+ DEBUG(0, ("Out of memory\n"));
+ state->cont(state->private_data, False, NULL, 0);
+ return;
+ }
+ }
if (state->local_alias_domain != NULL) {
struct winbindd_domain *local_domain = state->local_alias_domain;
@@ -1106,342 +1391,19 @@ static void gettoken_recvaliases(void *private_data, BOOL success,
state->cont(state->private_data, True, state->sids, state->num_sids);
}
-struct sid2uid_state {
- TALLOC_CTX *mem_ctx;
- DOM_SID sid;
- char *username;
- uid_t uid;
- void (*cont)(void *private_data, BOOL success, uid_t uid);
- void *private_data;
-};
-
-static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
- const char *dom_name, const char *name,
- enum SID_NAME_USE type);
-static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
-static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
-static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
-static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
-
-void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
- void (*cont)(void *private_data, BOOL success,
- uid_t uid),
- void *private_data)
-{
- struct sid2uid_state *state;
- NTSTATUS result;
- uid_t uid;
-
- if (idmap_proxyonly()) {
- DEBUG(10, ("idmap proxy only\n"));
- cont(private_data, False, 0);
- return;
- }
-
- /* Query only the local tdb, everything else might possibly block */
-
- result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(result)) {
- cont(private_data, True, uid);
- return;
- }
-
- state = TALLOC_ZERO_P(mem_ctx, struct sid2uid_state);
- if (state == NULL) {
- DEBUG(0, ("talloc failed\n"));
- cont(private_data, False, 0);
- return;
- }
-
- state->mem_ctx = mem_ctx;
- state->sid = *sid;
- state->cont = cont;
- state->private_data = private_data;
-
- /* Let's see if it's really a user before allocating a uid */
-
- winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
-}
-
-static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
- const char *dom_name, const char *name,
- enum SID_NAME_USE type)
-{
- struct sid2uid_state *state =
- talloc_get_type_abort(private_data, struct sid2uid_state);
-
- if (!success) {
- DEBUG(5, ("Could not trigger lookup_sid\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
- DEBUG(5, ("SID is not a user\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->username = talloc_strdup(state->mem_ctx, name);
-
- /* Ask the possibly blocking remote IDMAP */
-
- idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
- sid2uid_noalloc_recv, state);
-}
-
-static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
-{
- struct sid2uid_state *state =
- talloc_get_type_abort(private_data, struct sid2uid_state);
-
- if (success) {
- DEBUG(10, ("found uid for sid %s in remote backend\n",
- sid_string_static(&state->sid)));
- state->cont(state->private_data, True, uid);
- return;
- }
-
- if (lp_winbind_trusted_domains_only() &&
- (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
- DEBUG(10, ("Trying to go via nss\n"));
- winbindd_name2uid_async(state->mem_ctx, state->username,
- sid2uid_name2uid_recv, state);
- return;
- }
-
- /* To be done: Here we're going to try the unixinfo pipe */
-
- /* Now allocate a uid */
-
- idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
- sid2uid_alloc_recv, state);
-}
-
-static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
-{
- struct sid2uid_state *state =
- talloc_get_type_abort(private_data, struct sid2uid_state);
-
- if (!success) {
- DEBUG(5, ("Could not allocate uid\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->cont(state->private_data, True, uid);
-}
-
-static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
-{
- struct sid2uid_state *state =
- talloc_get_type_abort(private_data, struct sid2uid_state);
- unid_t id;
-
- if (!success) {
- DEBUG(5, ("Could not find uid for name %s\n",
- state->username));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->uid = uid;
-
- id.uid = uid;
- idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
- sid2uid_set_mapping_recv, state);
-}
-
-static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
-{
- struct sid2uid_state *state =
- talloc_get_type_abort(private_data, struct sid2uid_state);
-
- if (!success) {
- DEBUG(5, ("Could not set ID mapping for sid %s\n",
- sid_string_static(&state->sid)));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->cont(state->private_data, True, state->uid);
-}
-
-struct sid2gid_state {
- TALLOC_CTX *mem_ctx;
- DOM_SID sid;
- char *groupname;
- gid_t gid;
- void (*cont)(void *private_data, BOOL success, gid_t gid);
- void *private_data;
-};
-
-static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
- const char *dom_name, const char *name,
- enum SID_NAME_USE type);
-static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
-static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
-static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
-static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
-
-void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
- void (*cont)(void *private_data, BOOL success,
- gid_t gid),
- void *private_data)
-{
- struct sid2gid_state *state;
- NTSTATUS result;
- gid_t gid;
-
- if (idmap_proxyonly()) {
- DEBUG(10, ("idmap proxy only\n"));
- cont(private_data, False, 0);
- return;
- }
-
- /* Query only the local tdb, everything else might possibly block */
-
- result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(result)) {
- cont(private_data, True, gid);
- return;
- }
-
- state = TALLOC_ZERO_P(mem_ctx, struct sid2gid_state);
- if (state == NULL) {
- DEBUG(0, ("talloc failed\n"));
- cont(private_data, False, 0);
- return;
- }
-
- state->mem_ctx = mem_ctx;
- state->sid = *sid;
- state->cont = cont;
- state->private_data = private_data;
-
- /* Let's see if it's really a user before allocating a gid */
-
- winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
-}
-
-static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
- const char *dom_name, const char *name,
- enum SID_NAME_USE type)
-{
- struct sid2gid_state *state =
- talloc_get_type_abort(private_data, struct sid2gid_state);
-
- if (!success) {
- DEBUG(5, ("Could not trigger lookup_sid\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
- (type != SID_NAME_WKN_GRP))) {
- DEBUG(5, ("SID is not a group\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->groupname = talloc_strdup(state->mem_ctx, name);
-
- /* Ask the possibly blocking remote IDMAP and allocate */
-
- idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
- sid2gid_noalloc_recv, state);
-}
-
-static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
-{
- struct sid2gid_state *state =
- talloc_get_type_abort(private_data, struct sid2gid_state);
-
- if (success) {
- DEBUG(10, ("found gid for sid %s in remote backend\n",
- sid_string_static(&state->sid)));
- state->cont(state->private_data, True, gid);
- return;
- }
-
- if (lp_winbind_trusted_domains_only() &&
- (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
- DEBUG(10, ("Trying to go via nss\n"));
- winbindd_name2gid_async(state->mem_ctx, state->groupname,
- sid2gid_name2gid_recv, state);
- return;
- }
-
- /* To be done: Here we're going to try the unixinfo pipe */
-
- /* Now allocate a gid */
-
- idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
- sid2gid_alloc_recv, state);
-}
-
-static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
-{
- struct sid2gid_state *state =
- talloc_get_type_abort(private_data, struct sid2gid_state);
-
- if (!success) {
- DEBUG(5, ("Could not allocate gid\n"));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->cont(state->private_data, True, gid);
-}
-
-static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
-{
- struct sid2gid_state *state =
- talloc_get_type_abort(private_data, struct sid2gid_state);
- unid_t id;
-
- if (!success) {
- DEBUG(5, ("Could not find gid for name %s\n",
- state->groupname));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->gid = gid;
-
- id.gid = gid;
- idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
- sid2gid_set_mapping_recv, state);
-}
-
-static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
-{
- struct sid2gid_state *state =
- talloc_get_type_abort(private_data, struct sid2gid_state);
-
- if (!success) {
- DEBUG(5, ("Could not set ID mapping for sid %s\n",
- sid_string_static(&state->sid)));
- state->cont(state->private_data, False, 0);
- return;
- }
-
- state->cont(state->private_data, True, state->gid);
-}
-
static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ, const char *acct_name,
const char *full_name, const char *homedir,
- const char *shell, uint32 group_rid) = c;
+ const char *shell, uint32 gid, uint32 group_rid) =
+ (void (*)(void *, BOOL, const char *, const char *,
+ const char *, const char *, uint32, uint32))c;
if (!success) {
DEBUG(5, ("Could not trigger query_user\n"));
- cont(private_data, False, NULL, NULL, NULL, NULL, -1);
+ cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
return;
}
@@ -1449,6 +1411,7 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
response->data.user_info.full_name,
response->data.user_info.homedir,
response->data.user_info.shell,
+ response->data.user_info.primary_gid,
response->data.user_info.group_rid);
}
@@ -1459,6 +1422,7 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
const char *full_name,
const char *homedir,
const char *shell,
+ gid_t gid,
uint32 group_rid),
void *private_data)
{
@@ -1467,7 +1431,7 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
request.cmd = WINBINDD_DUAL_USERINFO;
sid_to_string(request.data.sid, sid);
do_async_domain(mem_ctx, domain, &request, query_user_recv,
- cont, private_data);
+ (void *)cont, private_data);
}
/* The following uid2sid/gid2sid functions has been contributed by
@@ -1477,7 +1441,8 @@ static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, const char *sid) = c;
+ void (*cont)(void *priv, BOOL succ, const char *sid) =
+ (void (*)(void *, BOOL, const char *))c;
if (!success) {
DEBUG(5, ("Could not trigger uid2sid\n"));
@@ -1503,7 +1468,8 @@ void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_UID2SID;
request.data.uid = uid;
- do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, cont, private_data);
+ do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv,
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
@@ -1517,7 +1483,7 @@ enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
(unsigned long) state->request.data.uid));
/* Find sid for this uid and return it, possibly ask the slow remote idmap */
- result = idmap_uid_to_sid(&sid, state->request.data.uid, ID_EMPTY);
+ result = idmap_uid_to_sid(&sid, state->request.data.uid);
if (NT_STATUS_IS_OK(result)) {
sid_to_string(state->response.data.sid.sid, &sid);
@@ -1532,7 +1498,8 @@ static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
- void (*cont)(void *priv, BOOL succ, const char *sid) = c;
+ void (*cont)(void *priv, BOOL succ, const char *sid) =
+ (void (*)(void *, BOOL, const char *))c;
if (!success) {
DEBUG(5, ("Could not trigger gid2sid\n"));
@@ -1558,7 +1525,8 @@ void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_GID2SID;
request.data.gid = gid;
- do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, cont, private_data);
+ do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv,
+ (void *)cont, private_data);
}
enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
@@ -1572,7 +1540,7 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
(unsigned long) state->request.data.gid));
/* Find sid for this gid and return it, possibly ask the slow remote idmap */
- result = idmap_gid_to_sid(&sid, state->request.data.gid, ID_EMPTY);
+ result = idmap_gid_to_sid(&sid, state->request.data.gid);
if (NT_STATUS_IS_OK(result)) {
sid_to_string(state->response.data.sid.sid, &sid);
@@ -1585,3 +1553,49 @@ enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
return WINBINDD_ERROR;
}
+
+static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success,
+ struct winbindd_response *response,
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, BOOL succ) =
+ (void (*)(void *, BOOL))c;
+
+ if (!success) {
+ DEBUG(5, ("Could not trigger a map dump\n"));
+ cont(private_data, False);
+ return;
+ }
+
+ if (response->result != WINBINDD_OK) {
+ DEBUG(5, ("idmap dump maps returned an error\n"));
+ cont(private_data, False);
+ return;
+ }
+
+ cont(private_data, True);
+}
+
+void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size,
+ void (*cont)(void *private_data, BOOL success),
+ void *private_data)
+{
+ struct winbindd_request request;
+ ZERO_STRUCT(request);
+ request.cmd = WINBINDD_DUAL_DUMP_MAPS;
+ request.extra_data.data = (char *)data;
+ request.extra_len = size;
+ do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv,
+ (void *)cont, private_data);
+}
+
+enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid));
+
+ idmap_dump_maps((char *)state->request.extra_data.data);
+
+ return WINBINDD_OK;
+}
+
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index cdb86f9f61b..908d6ed19ae 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -29,6 +29,12 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+extern struct winbindd_methods reconnect_methods;
+extern BOOL opt_nocache;
+#ifdef HAVE_ADS
+extern struct winbindd_methods ads_methods;
+#endif
+
/* Global online/offline state - False when online. winbindd starts up online
and sets this to true if the first query fails and there's an entry in
the cache tdb telling us to stay offline. */
@@ -66,7 +72,7 @@ void winbindd_check_cache_size(time_t t)
return;
}
- if (fstat(wcache->tdb->fd, &st) == -1) {
+ if (fstat(tdb_fd(wcache->tdb), &st) == -1) {
DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) ));
return;
}
@@ -87,10 +93,11 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
struct winbindd_domain *our_domain = domain;
#endif
- /* we have to know what type of domain we are dealing with first */
+ /* We have to know what type of domain we are dealing with first. */
- if ( !domain->initialized )
- set_dc_type_and_flags( domain );
+ if ( !domain->initialized ) {
+ init_dc_connection( domain );
+ }
/*
OK. listen up becasue I'm only going to say this once.
@@ -111,10 +118,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
*/
if (!domain->backend) {
- extern struct winbindd_methods reconnect_methods;
#ifdef HAVE_ADS
- extern struct winbindd_methods ads_methods;
-
/* find our domain first so we can figure out if we
are joined to a kerberized domain */
@@ -215,9 +219,9 @@ static NTTIME centry_nttime(struct cache_entry *centry)
centry->len - centry->ofs));
smb_panic("centry_nttime");
}
- ret.low = IVAL(centry->data, centry->ofs);
+ ret = IVAL(centry->data, centry->ofs);
centry->ofs += 4;
- ret.high = IVAL(centry->data, centry->ofs);
+ ret += (uint64_t)IVAL(centry->data, centry->ofs) << 32;
centry->ofs += 4;
return ret;
}
@@ -259,7 +263,7 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
smb_panic("centry_string");
}
- ret = TALLOC(mem_ctx, len+1);
+ ret = TALLOC_ARRAY(mem_ctx, char, len+1);
if (!ret) {
smb_panic("centry_string out of memory\n");
}
@@ -282,13 +286,13 @@ static char *centry_hash16(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
if (len != 16) {
DEBUG(0,("centry corruption? hash len (%u) != 16\n",
len ));
- smb_panic("centry_hash16");
+ return NULL;
}
if (centry->len - centry->ofs < 16) {
DEBUG(0,("centry corruption? needed 16 bytes, have %d\n",
centry->len - centry->ofs));
- smb_panic("centry_hash16");
+ return NULL;
}
ret = TALLOC_ARRAY(mem_ctx, char, 16);
@@ -372,7 +376,7 @@ static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now )
static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain )
{
- TDB_DATA data, key;
+ TDB_DATA data;
fstring key_str;
char buf[8];
@@ -382,15 +386,13 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain )
}
fstr_sprintf( key_str, "SEQNUM/%s", domain->name );
- key.dptr = key_str;
- key.dsize = strlen(key_str)+1;
SIVAL(buf, 0, domain->sequence_number);
SIVAL(buf, 4, domain->last_seq_check);
data.dptr = buf;
data.dsize = 8;
- if ( tdb_store( wcache->tdb, key, data, TDB_REPLACE) == -1 ) {
+ if ( tdb_store_bystring( wcache->tdb, key_str, data, TDB_REPLACE) == -1 ) {
DEBUG(10,("store_cache_seqnum: tdb_store fail key [%s]\n", key_str ));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -443,6 +445,11 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
status = domain->backend->sequence_number(domain, &domain->sequence_number);
+ /* the above call could have set our domain->backend to NULL when
+ * coming from offline to online mode, make sure to reinitialize the
+ * backend - Guenther */
+ get_cache( domain );
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("refresh_sequence_number: failed with %s\n", nt_errstr(status)));
domain->sequence_number = DOM_SEQUENCE_NONE;
@@ -473,12 +480,10 @@ static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, s
return False;
}
- /* when the domain is offline and we havent checked in the last 30
- * seconds if it has become online again, return the cached entry.
+ /* when the domain is offline return the cached entry.
* This deals with transient offline states... */
- if (!domain->online &&
- !NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, domain->dcname))) {
+ if (!domain->online) {
DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
keystr, domain->name ));
return False;
@@ -556,8 +561,6 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
char *kstr;
struct cache_entry *centry;
- extern BOOL opt_nocache;
-
if (opt_nocache) {
return NULL;
}
@@ -591,6 +594,24 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
return centry;
}
+static void wcache_delete(const char *format, ...) PRINTF_ATTRIBUTE(1,2);
+static void wcache_delete(const char *format, ...)
+{
+ va_list ap;
+ char *kstr;
+ TDB_DATA key;
+
+ va_start(ap, format);
+ smb_xvasprintf(&kstr, format, ap);
+ va_end(ap);
+
+ key.dptr = kstr;
+ key.dsize = strlen(kstr);
+
+ tdb_delete(wcache->tdb, key);
+ free(kstr);
+}
+
/*
make sure we have at least len bytes available in a centry
*/
@@ -599,7 +620,8 @@ static void centry_expand(struct cache_entry *centry, uint32 len)
if (centry->len - centry->ofs >= len)
return;
centry->len *= 2;
- centry->data = SMB_REALLOC(centry->data, centry->len);
+ centry->data = SMB_REALLOC_ARRAY(centry->data, unsigned char,
+ centry->len);
if (!centry->data) {
DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len));
smb_panic("out of memory in centry_expand");
@@ -684,9 +706,9 @@ static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid)
static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
{
centry_expand(centry, 8);
- SIVAL(centry->data, centry->ofs, nt.low);
+ SIVAL(centry->data, centry->ofs, nt & 0xFFFFFFFF);
centry->ofs += 4;
- SIVAL(centry->data, centry->ofs, nt.high);
+ SIVAL(centry->data, centry->ofs, nt >> 32);
centry->ofs += 4;
}
@@ -747,7 +769,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...)
static void wcache_save_name_to_sid(struct winbindd_domain *domain,
NTSTATUS status, const char *domain_name,
const char *name, const DOM_SID *sid,
- enum SID_NAME_USE type)
+ enum lsa_SidType type)
{
struct cache_entry *centry;
fstring uname;
@@ -766,7 +788,7 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
}
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status,
- const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type)
+ const DOM_SID *sid, const char *domain_name, const char *name, enum lsa_SidType type)
{
struct cache_entry *centry;
fstring sid_string;
@@ -805,6 +827,7 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
centry_put_string(centry, info->full_name);
centry_put_string(centry, info->homedir);
centry_put_string(centry, info->shell);
+ centry_put_uint32(centry, info->primary_gid);
centry_put_sid(centry, &info->user_sid);
centry_put_sid(centry, &info->group_sid);
centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid));
@@ -882,11 +905,14 @@ NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID
return NT_STATUS_OK;
}
-/* Lookup creds for a SID */
+/* Lookup creds for a SID - copes with old (unsalted) creds as well
+ as new salted ones. */
+
NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
- const uint8 **cached_nt_pass)
+ const uint8 **cached_nt_pass,
+ const uint8 **cached_salt)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
@@ -906,19 +932,48 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
return NT_STATUS_INVALID_SID;
}
+ /* Try and get a salted cred first. If we can't
+ fall back to an unsalted cred. */
+
centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid));
-
if (!centry) {
DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n",
- sid_string_static(sid)));
+ sid_string_static(sid)));
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
t = centry_time(centry);
+
+ /* In the salted case this isn't actually the nt_hash itself,
+ but the MD5 of the salt + nt_hash. Let the caller
+ sort this out. It can tell as we only return the cached_salt
+ if we are returning a salted cred. */
+
*cached_nt_pass = (const uint8 *)centry_hash16(centry, mem_ctx);
+ if (*cached_nt_pass == NULL) {
+ const char *sidstr = sid_string_static(sid);
+
+ /* Bad (old) cred cache. Delete and pretend we
+ don't have it. */
+ DEBUG(0,("wcache_get_creds: bad entry for [CRED/%s] - deleting\n",
+ sidstr));
+ wcache_delete("CRED/%s", sidstr);
+ centry_free(centry);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ /* We only have 17 bytes more data in the salted cred case. */
+ if (centry->len - centry->ofs == 17) {
+ *cached_salt = (const uint8 *)centry_hash16(centry, mem_ctx);
+ } else {
+ *cached_salt = NULL;
+ }
#if DEBUG_PASSWORD
- dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
+ dump_data(100, (const char *)*cached_nt_pass, NT_HASH_LEN);
+ if (*cached_salt) {
+ dump_data(100, (const char *)*cached_salt, NT_HASH_LEN);
+ }
#endif
status = centry->status;
@@ -929,6 +984,8 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
return status;
}
+/* Store creds for a SID - only writes out new salted ones. */
+
NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
@@ -937,6 +994,8 @@ NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
struct cache_entry *centry;
fstring sid_string;
uint32 rid;
+ uint8 cred_salt[NT_HASH_LEN];
+ uint8 salted_hash[NT_HASH_LEN];
if (is_null_sid(sid)) {
return NT_STATUS_INVALID_SID;
@@ -956,7 +1015,13 @@ NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
#endif
centry_put_time(centry, time(NULL));
- centry_put_hash16(centry, nt_pass);
+
+ /* Create a salt and then salt the hash. */
+ generate_random_buffer(cred_salt, NT_HASH_LEN);
+ E_md5hash(cred_salt, nt_pass, salted_hash);
+
+ centry_put_hash16(centry, salted_hash);
+ centry_put_hash16(centry, cred_salt);
centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid));
DEBUG(10,("wcache_save_creds: %s\n", sid_string));
@@ -1060,7 +1125,7 @@ do_query:
centry_put_string(centry, (*info)[i].shell);
centry_put_sid(centry, &(*info)[i].user_sid);
centry_put_sid(centry, &(*info)[i].group_sid);
- if (domain->backend->consistent) {
+ if (domain->backend && domain->backend->consistent) {
/* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid(domain, NT_STATUS_OK,
domain->name,
@@ -1244,7 +1309,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
@@ -1259,7 +1324,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
if (!centry)
goto do_query;
- *type = (enum SID_NAME_USE)centry_uint32(centry);
+ *type = (enum lsa_SidType)centry_uint32(centry);
status = centry->status;
if (NT_STATUS_IS_OK(status)) {
centry_sid(centry, mem_ctx, sid);
@@ -1313,7 +1378,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
const DOM_SID *sid,
char **domain_name,
char **name,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
@@ -1327,7 +1392,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
if (!centry)
goto do_query;
if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum SID_NAME_USE)centry_uint32(centry);
+ *type = (enum lsa_SidType)centry_uint32(centry);
*domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx);
}
@@ -1369,6 +1434,128 @@ do_query:
return status;
}
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ uint32 *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ size_t i;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ BOOL have_mapped;
+ BOOL have_unmapped;
+
+ *domain_name = NULL;
+ *names = NULL;
+ *types = NULL;
+
+ if (!cache->tdb) {
+ goto do_query;
+ }
+
+ if (num_rids == 0) {
+ return NT_STATUS_OK;
+ }
+
+ *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+
+ if ((*names == NULL) || (*types == NULL)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto error;
+ }
+
+ have_mapped = have_unmapped = False;
+
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+ struct cache_entry *centry;
+
+ if (!sid_compose(&sid, domain_sid, rids[i])) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto error;
+ }
+
+ centry = wcache_fetch(cache, domain, "SN/%s",
+ sid_string_static(&sid));
+ if (!centry) {
+ goto do_query;
+ }
+
+ (*types)[i] = SID_NAME_UNKNOWN;
+ (*names)[i] = talloc_strdup(*names, "");
+
+ if (NT_STATUS_IS_OK(centry->status)) {
+ char *dom;
+ have_mapped = True;
+ (*types)[i] = (enum lsa_SidType)centry_uint32(centry);
+ dom = centry_string(centry, mem_ctx);
+ if (*domain_name == NULL) {
+ *domain_name = dom;
+ } else {
+ talloc_free(dom);
+ }
+ (*names)[i] = centry_string(centry, *names);
+ } else {
+ have_unmapped = True;
+ }
+
+ centry_free(centry);
+ }
+
+ if (!have_mapped) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+ if (!have_unmapped) {
+ return NT_STATUS_OK;
+ }
+ return STATUS_SOME_UNMAPPED;
+
+ do_query:
+
+ TALLOC_FREE(*names);
+ TALLOC_FREE(*types);
+
+ result = domain->backend->rids_to_names(domain, mem_ctx, domain_sid,
+ rids, num_rids, domain_name,
+ names, types);
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+ return result;
+ }
+
+ refresh_sequence_number(domain, False);
+
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+ NTSTATUS status;
+
+ if (!sid_compose(&sid, domain_sid, rids[i])) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto error;
+ }
+
+ status = (*types)[i] == SID_NAME_UNKNOWN ?
+ NT_STATUS_NONE_MAPPED : NT_STATUS_OK;
+
+ wcache_save_sid_to_name(domain, status, &sid, *domain_name,
+ (*names)[i], (*types)[i]);
+ }
+
+ return result;
+
+ error:
+
+ TALLOC_FREE(*names);
+ TALLOC_FREE(*types);
+ return result;
+}
+
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -1403,6 +1590,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
info->full_name = centry_string(centry, mem_ctx);
info->homedir = centry_string(centry, mem_ctx);
info->shell = centry_string(centry, mem_ctx);
+ info->primary_gid = centry_uint32(centry);
centry_sid(centry, mem_ctx, &info->user_sid);
centry_sid(centry, mem_ctx, &info->group_sid);
status = centry->status;
@@ -1421,7 +1609,7 @@ do_query:
if (!NT_STATUS_IS_OK(domain->last_status))
return domain->last_status;
- DEBUG(10,("sid_to_name: [Cached] - doing backend query for info for domain %s\n",
+ DEBUG(10,("query_user: [Cached] - doing backend query for info for domain %s\n",
domain->name ));
status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
@@ -1967,7 +2155,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
fstr_sprintf(key_str, "DR/%d", pid);
if (tdb_store(wcache->tdb, string_tdb_data(key_str),
- make_tdb_data((void *)response, sizeof(*response)),
+ make_tdb_data((const char *)response, sizeof(*response)),
TDB_REPLACE) == -1)
return;
@@ -1981,7 +2169,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
fstr_sprintf(key_str, "DE/%d", pid);
if (tdb_store(wcache->tdb, string_tdb_data(key_str),
- make_tdb_data(response->extra_data.data,
+ make_tdb_data((const char *)response->extra_data.data,
response->length - sizeof(*response)),
TDB_REPLACE) == 0)
return;
@@ -2066,7 +2254,7 @@ void cache_cleanup_response(pid_t pid)
BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **domain_name, const char **name,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
struct winbindd_domain *domain;
struct winbind_cache *cache;
@@ -2090,7 +2278,7 @@ BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
}
if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum SID_NAME_USE)centry_uint32(centry);
+ *type = (enum lsa_SidType)centry_uint32(centry);
*domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx);
}
@@ -2104,7 +2292,7 @@ BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
struct winbindd_domain *domain;
struct winbind_cache *cache;
@@ -2132,7 +2320,7 @@ BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
}
if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum SID_NAME_USE)centry_uint32(centry);
+ *type = (enum lsa_SidType)centry_uint32(centry);
centry_sid(centry, mem_ctx, sid);
}
@@ -2144,7 +2332,7 @@ BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
void cache_name2sid(struct winbindd_domain *domain,
const char *domain_name, const char *name,
- enum SID_NAME_USE type, const DOM_SID *sid)
+ enum lsa_SidType type, const DOM_SID *sid)
{
refresh_sequence_number(domain, False);
wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
@@ -2174,8 +2362,6 @@ static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
/* flush the cache */
void wcache_flush_cache(void)
{
- extern BOOL opt_nocache;
-
if (!wcache)
return;
if (wcache->tdb) {
@@ -2345,7 +2531,6 @@ done:
BOOL set_global_winbindd_state_offline(void)
{
TDB_DATA data;
- int err;
DEBUG(10,("set_global_winbindd_state_offline: offline requested.\n"));
@@ -2367,21 +2552,16 @@ BOOL set_global_winbindd_state_offline(void)
return True;
}
- wcache->tdb->ecode = 0;
-
data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
- /* As this is a key with no data we don't need to free, we
- check for existence by looking at tdb_err. */
-
- err = tdb_error(wcache->tdb);
-
- if (err == TDB_ERR_NOEXIST) {
+ if (!data.dptr || data.dsize != 4) {
DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
+ SAFE_FREE(data.dptr);
return False;
} else {
DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
global_winbindd_offline_state = True;
+ SAFE_FREE(data.dptr);
return True;
}
}
@@ -2409,7 +2589,7 @@ void set_global_winbindd_state_online(void)
tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE");
}
-BOOL get_global_winbindd_state_online(void)
+BOOL get_global_winbindd_state_offline(void)
{
return global_winbindd_offline_state;
}
@@ -2422,6 +2602,7 @@ struct winbindd_methods cache_methods = {
enum_local_groups,
name_to_sid,
sid_to_name,
+ rids_to_names,
query_user,
lookup_usergroups,
lookup_useraliases,
diff --git a/source/nsswitch/winbindd_ccache_access.c b/source/nsswitch/winbindd_ccache_access.c
new file mode 100644
index 00000000000..f439a0457d7
--- /dev/null
+++ b/source/nsswitch/winbindd_ccache_access.c
@@ -0,0 +1,284 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Winbind daemon - cached credentials funcions
+
+ Copyright (C) Robert O'Callahan 2006
+ Copyright (C) Jeremy Allison 2006 (minor fixes to fit into Samba and
+ protect against integer wrap).
+
+ 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 "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+static BOOL client_can_access_ccache_entry(uid_t client_uid,
+ struct WINBINDD_MEMORY_CREDS *entry)
+{
+ if (client_uid == entry->uid || client_uid == 0) {
+ DEBUG(10, ("Access granted to uid %d\n", client_uid));
+ return True;
+ }
+
+ DEBUG(1, ("Access denied to uid %d (expected %d)\n", client_uid, entry->uid));
+ return False;
+}
+
+static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
+ const char *domain,
+ const unsigned char lm_hash[LM_HASH_LEN],
+ const unsigned char nt_hash[NT_HASH_LEN],
+ const DATA_BLOB initial_msg,
+ const DATA_BLOB challenge_msg,
+ DATA_BLOB *auth_msg)
+{
+ NTSTATUS status;
+ NTLMSSP_STATE *ntlmssp_state = NULL;
+ DATA_BLOB dummy_msg, reply;
+
+ status = ntlmssp_client_start(&ntlmssp_state);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not start NTLMSSP client: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ status = ntlmssp_set_username(ntlmssp_state, username);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not set username: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ status = ntlmssp_set_domain(ntlmssp_state, domain);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not set domain: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ status = ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not set hashes: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ /* We need to get our protocol handler into the right state. So first
+ we ask it to generate the initial message. Actually the client has already
+ sent its own initial message, so we're going to drop this one on the floor.
+ The client might have sent a different message, for example with different
+ negotiation options, but as far as I can tell this won't hurt us. (Unless
+ the client sent a different username or domain, in which case that's their
+ problem for telling us the wrong username or domain.)
+ Since we have a copy of the initial message that the client sent, we could
+ resolve any discrepancies if we had to.
+ */
+ dummy_msg = data_blob(NULL, 0);
+ reply = data_blob(NULL, 0);
+ status = ntlmssp_update(ntlmssp_state, dummy_msg, &reply);
+ data_blob_free(&dummy_msg);
+ data_blob_free(&reply);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DEBUG(1, ("Failed to create initial message! [%s]\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ /* Now we are ready to handle the server's actual response. */
+ status = ntlmssp_update(ntlmssp_state, challenge_msg, &reply);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
+ DEBUG(1, ("We didn't get a response to the challenge! [%s]\n",
+ nt_errstr(status)));
+ data_blob_free(&reply);
+ goto done;
+ }
+ *auth_msg = reply;
+ status = NT_STATUS_OK;
+
+done:
+ ntlmssp_end(&ntlmssp_state);
+ return status;
+}
+
+static BOOL check_client_uid(struct winbindd_cli_state *state, uid_t uid)
+{
+ int ret;
+ uid_t ret_uid;
+
+ ret_uid = (uid_t)-1;
+
+ ret = sys_getpeereid(state->sock, &ret_uid);
+ if (ret != 0) {
+ DEBUG(1, ("check_client_uid: Could not get socket peer uid: %s; "
+ "denying access\n", strerror(errno)));
+ return False;
+ }
+
+ if (uid != ret_uid) {
+ DEBUG(1, ("check_client_uid: Client lied about its uid: said %d, "
+ "actually was %d; denying access\n",
+ uid, ret_uid));
+ return False;
+ }
+
+ return True;
+}
+
+void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ fstring name_domain, name_user;
+
+ /* Ensure null termination */
+ state->request.data.ccache_ntlm_auth.user[
+ sizeof(state->request.data.ccache_ntlm_auth.user)-1]='\0';
+
+ DEBUG(3, ("[%5lu]: perform NTLM auth on behalf of user %s\n", (unsigned long)state->pid,
+ state->request.data.ccache_ntlm_auth.user));
+
+ /* Parse domain and username */
+
+ if (!canonicalize_username(state->request.data.ccache_ntlm_auth.user,
+ name_domain, name_user)) {
+ DEBUG(5,("winbindd_ccache_ntlm_auth: cannot parse domain and user from name [%s]\n",
+ state->request.data.ccache_ntlm_auth.user));
+ request_error(state);
+ return;
+ }
+
+ domain = find_auth_domain(state, name_domain);
+
+ if (domain == NULL) {
+ DEBUG(5,("winbindd_ccache_ntlm_auth: can't get domain [%s]\n",
+ name_domain));
+ request_error(state);
+ return;
+ }
+
+ if (!check_client_uid(state, state->request.data.ccache_ntlm_auth.uid)) {
+ request_error(state);
+ return;
+ }
+
+ sendto_domain(state, domain);
+}
+
+enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
+ struct WINBINDD_MEMORY_CREDS *entry;
+ DATA_BLOB initial, challenge, auth;
+ fstring name_domain, name_user;
+ uint32 initial_blob_len, challenge_blob_len, extra_len;
+
+ /* Ensure null termination */
+ state->request.data.ccache_ntlm_auth.user[
+ sizeof(state->request.data.ccache_ntlm_auth.user)-1]='\0';
+
+ DEBUG(3, ("winbindd_dual_ccache_ntlm_auth: [%5lu]: perform NTLM auth on "
+ "behalf of user %s (dual)\n", (unsigned long)state->pid,
+ state->request.data.ccache_ntlm_auth.user));
+
+ /* validate blob lengths */
+ initial_blob_len = state->request.data.ccache_ntlm_auth.initial_blob_len;
+ challenge_blob_len = state->request.data.ccache_ntlm_auth.challenge_blob_len;
+ extra_len = state->request.extra_len;
+
+ if (initial_blob_len > extra_len || challenge_blob_len > extra_len ||
+ initial_blob_len + challenge_blob_len > extra_len ||
+ initial_blob_len + challenge_blob_len < initial_blob_len ||
+ initial_blob_len + challenge_blob_len < challenge_blob_len) {
+
+ DEBUG(10,("winbindd_dual_ccache_ntlm_auth: blob lengths overrun "
+ "or wrap. Buffer [%d+%d > %d]\n",
+ initial_blob_len,
+ challenge_blob_len,
+ extra_len));
+ goto process_result;
+ }
+
+ /* Parse domain and username */
+ if (!parse_domain_user(state->request.data.ccache_ntlm_auth.user, name_domain, name_user)) {
+ DEBUG(10,("winbindd_dual_ccache_ntlm_auth: cannot parse "
+ "domain and user from name [%s]\n",
+ state->request.data.ccache_ntlm_auth.user));
+ goto process_result;
+ }
+
+ entry = find_memory_creds_by_name(state->request.data.ccache_ntlm_auth.user);
+ if (entry == NULL || entry->nt_hash == NULL || entry->lm_hash == NULL) {
+ DEBUG(10,("winbindd_dual_ccache_ntlm_auth: could not find "
+ "credentials for user %s\n",
+ state->request.data.ccache_ntlm_auth.user));
+ goto process_result;
+ }
+
+ DEBUG(10,("winbindd_dual_ccache_ntlm_auth: found ccache [%s]\n", entry->username));
+
+ if (!client_can_access_ccache_entry(state->request.data.ccache_ntlm_auth.uid, entry)) {
+ goto process_result;
+ }
+
+ if (initial_blob_len == 0 && challenge_blob_len == 0) {
+ /* this is just a probe to see if credentials are available. */
+ result = NT_STATUS_OK;
+ state->response.data.ccache_ntlm_auth.auth_blob_len = 0;
+ goto process_result;
+ }
+
+ initial = data_blob(state->request.extra_data.data, initial_blob_len);
+ challenge = data_blob(state->request.extra_data.data + initial_blob_len,
+ state->request.data.ccache_ntlm_auth.challenge_blob_len);
+
+ if (!initial.data || !challenge.data) {
+ result = NT_STATUS_NO_MEMORY;
+ } else {
+ result = do_ntlm_auth_with_hashes(name_user, name_domain,
+ entry->lm_hash, entry->nt_hash,
+ initial, challenge, &auth);
+ }
+
+ data_blob_free(&initial);
+ data_blob_free(&challenge);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto process_result;
+ }
+
+ state->response.extra_data.data = smb_xmemdup(auth.data, auth.length);
+ if (!state->response.extra_data.data) {
+ result = NT_STATUS_NO_MEMORY;
+ goto process_result;
+ }
+ state->response.length += auth.length;
+ state->response.data.ccache_ntlm_auth.auth_blob_len = auth.length;
+
+ data_blob_free(&auth);
+
+ process_result:
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+}
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 98e799851fc..010d38fde97 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -7,6 +7,7 @@
Copyright (C) Andrew Bartlett 2002
Copyright (C) Gerald (Jerry) Carter 2003-2005.
Copyright (C) Volker Lendecke 2004-2005
+ Copyright (C) Jeremy Allison 2006
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
@@ -64,6 +65,424 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+struct dc_name_ip {
+ fstring name;
+ struct in_addr ip;
+};
+
+extern struct winbindd_methods reconnect_methods;
+extern BOOL override_logfile;
+
+static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
+static void set_dc_type_and_flags( struct winbindd_domain *domain );
+static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+ struct dc_name_ip **dcs, int *num_dcs);
+
+/****************************************************************
+ Child failed to find DC's. Reschedule check.
+****************************************************************/
+
+static void msg_failed_to_go_online(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
+{
+ struct winbindd_domain *domain;
+ const char *domainname = (const char *)buf;
+
+ if (buf == NULL || len == 0) {
+ return;
+ }
+
+ DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
+
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if (domain->internal) {
+ continue;
+ }
+
+ if (strequal(domain->name, domainname)) {
+ if (domain->online) {
+ /* We're already online, ignore. */
+ DEBUG(5,("msg_fail_to_go_online: domain %s "
+ "already online.\n", domainname));
+ continue;
+ }
+
+ /* Reschedule the online check. */
+ set_domain_offline(domain);
+ break;
+ }
+ }
+}
+
+/****************************************************************
+ Actually cause a reconnect from a message.
+****************************************************************/
+
+static void msg_try_to_go_online(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
+{
+ struct winbindd_domain *domain;
+ const char *domainname = (const char *)buf;
+
+ if (buf == NULL || len == 0) {
+ return;
+ }
+
+ DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
+
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if (domain->internal) {
+ continue;
+ }
+
+ if (strequal(domain->name, domainname)) {
+
+ if (domain->online) {
+ /* We're already online, ignore. */
+ DEBUG(5,("msg_try_to_go_online: domain %s "
+ "already online.\n", domainname));
+ continue;
+ }
+
+ /* This call takes care of setting the online
+ flag to true if we connected, or re-adding
+ the offline handler if false. Bypasses online
+ check so always does network calls. */
+
+ init_dc_connection_network(domain);
+ break;
+ }
+ }
+}
+
+/****************************************************************
+ Fork a child to try and contact a DC. Do this as contacting a
+ DC requires blocking lookups and we don't want to block our
+ parent.
+****************************************************************/
+
+static BOOL fork_child_dc_connect(struct winbindd_domain *domain)
+{
+ struct dc_name_ip *dcs = NULL;
+ int num_dcs = 0;
+ TALLOC_CTX *mem_ctx = NULL;
+ pid_t child_pid;
+ pid_t parent_pid = sys_getpid();
+
+ /* Stop zombies */
+ CatchChild();
+
+ message_block();
+
+ child_pid = sys_fork();
+
+ if (child_pid == -1) {
+ DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
+ message_unblock();
+ return False;
+ }
+
+ if (child_pid != 0) {
+ /* Parent */
+ message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
+ msg_try_to_go_online, NULL);
+ message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
+ msg_failed_to_go_online, NULL);
+ message_unblock();
+ return True;
+ }
+
+ /* Child. */
+
+ /* Leave messages blocked - we will never process one. */
+
+ /* tdb needs special fork handling */
+ if (tdb_reopen_all(1) == -1) {
+ DEBUG(0,("tdb_reopen_all failed.\n"));
+ _exit(0);
+ }
+
+ close_conns_after_fork();
+
+ if (!override_logfile) {
+ pstring logfile;
+ pstr_sprintf(logfile, "%s/log.winbindd-dc-connect", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ reopen_logs();
+ }
+
+ mem_ctx = talloc_init("fork_child_dc_connect");
+ if (!mem_ctx) {
+ DEBUG(0,("talloc_init failed.\n"));
+ _exit(0);
+ }
+
+ if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
+ /* Still offline ? Can't find DC's. */
+ message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
+ domain->name,
+ strlen(domain->name)+1, False);
+ _exit(0);
+ }
+
+ /* We got a DC. Send a message to our parent to get it to
+ try and do the same. */
+
+ message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
+ domain->name,
+ strlen(domain->name)+1, False);
+ _exit(0);
+}
+
+/****************************************************************
+ Handler triggered if we're offline to try and detect a DC.
+****************************************************************/
+
+static void check_domain_online_handler(struct event_context *ctx,
+ struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ struct winbindd_domain *domain =
+ (struct winbindd_domain *)private_data;
+
+ DEBUG(10,("check_domain_online_handler: called for domain %s\n",
+ domain->name ));
+
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+
+ /* Are we still in "startup" mode ? */
+
+ if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
+ /* No longer in "startup" mode. */
+ DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
+ domain->name ));
+ domain->startup = False;
+ }
+
+ /* We've been told to stay offline, so stay
+ that way. */
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ /* Fork a child to test if it can contact a DC.
+ If it can then send ourselves a message to
+ cause a reconnect. */
+
+ fork_child_dc_connect(domain);
+}
+
+/****************************************************************
+ If we're still offline setup the timeout check.
+****************************************************************/
+
+static void calc_new_online_timeout_check(struct winbindd_domain *domain)
+{
+ int wbc = lp_winbind_cache_time();
+
+ if (domain->startup) {
+ domain->check_online_timeout = 10;
+ } else if (domain->check_online_timeout < wbc) {
+ domain->check_online_timeout = wbc;
+ }
+}
+
+/****************************************************************
+ Set domain offline and also add handler to put us back online
+ if we detect a DC.
+****************************************************************/
+
+void set_domain_offline(struct winbindd_domain *domain)
+{
+ DEBUG(10,("set_domain_offline: called for domain %s\n",
+ domain->name ));
+
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+
+ if (domain->internal) {
+ DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
+ domain->name ));
+ return;
+ }
+
+ domain->online = False;
+
+ /* Offline domains are always initialized. They're
+ re-initialized when they go back online. */
+
+ domain->initialized = True;
+
+ /* We only add the timeout handler that checks and
+ allows us to go back online when we've not
+ been told to remain offline. */
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ /* If we're in statup mode, check again in 10 seconds, not in
+ lp_winbind_cache_time() seconds (which is 5 mins by default). */
+
+ calc_new_online_timeout_check(domain);
+
+ domain->check_online_event = event_add_timed(winbind_event_context(),
+ NULL,
+ timeval_current_ofs(domain->check_online_timeout,0),
+ "check_domain_online_handler",
+ check_domain_online_handler,
+ domain);
+
+ /* The above *has* to succeed for winbindd to work. */
+ if (!domain->check_online_event) {
+ smb_panic("set_domain_offline: failed to add online handler.\n");
+ }
+
+ DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
+ domain->name ));
+}
+
+/****************************************************************
+ Set domain online - if allowed.
+****************************************************************/
+
+static void set_domain_online(struct winbindd_domain *domain)
+{
+ struct timeval now;
+
+ DEBUG(10,("set_domain_online: called for domain %s\n",
+ domain->name ));
+
+ if (domain->internal) {
+ DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
+ domain->name ));
+ return;
+ }
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ /* If we are waiting to get a krb5 ticket, trigger immediately. */
+ GetTimeOfDay(&now);
+ set_event_dispatch_time(winbind_event_context(),
+ "krb5_ticket_gain_handler", now);
+
+ /* Ok, we're out of any startup mode now... */
+ domain->startup = False;
+
+ if (domain->online == False) {
+ /* We were offline - now we're online. We default to
+ using the MS-RPC backend if we started offline,
+ and if we're going online for the first time we
+ should really re-initialize the backends and the
+ checks to see if we're talking to an AD or NT domain.
+ */
+
+ domain->initialized = False;
+
+ /* 'reconnect_methods' is the MS-RPC backend. */
+ if (domain->backend == &reconnect_methods) {
+ domain->backend = NULL;
+ }
+ }
+
+ /* Ensure we have no online timeout checks. */
+ domain->check_online_timeout = 0;
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+
+ /* Ensure we ignore any pending child messages. */
+ message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
+ message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
+
+ domain->online = True;
+}
+
+/****************************************************************
+ Requested to set a domain online.
+****************************************************************/
+
+void set_domain_online_request(struct winbindd_domain *domain)
+{
+ struct timeval tev;
+
+ DEBUG(10,("set_domain_online_request: called for domain %s\n",
+ domain->name ));
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ /* We've been told it's safe to go online and
+ try and connect to a DC. But I don't believe it
+ because network manager seems to lie.
+ Wait at least 5 seconds. Heuristics suck... */
+
+ if (!domain->check_online_event) {
+ /* If we've come from being globally offline we
+ don't have a check online event handler set.
+ We need to add one now we're trying to go
+ back online. */
+
+ DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
+ domain->name ));
+
+ domain->check_online_event = event_add_timed(winbind_event_context(),
+ NULL,
+ timeval_current_ofs(5, 0),
+ "check_domain_online_handler",
+ check_domain_online_handler,
+ domain);
+
+ /* The above *has* to succeed for winbindd to work. */
+ if (!domain->check_online_event) {
+ smb_panic("set_domain_online_request: failed to add online handler.\n");
+ }
+ }
+
+ GetTimeOfDay(&tev);
+
+ /* Go into "startup" mode again. */
+ domain->startup_time = tev.tv_sec;
+ domain->startup = True;
+
+ tev.tv_sec += 5;
+
+ set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
+}
+
+/****************************************************************
+ Add -ve connection cache entries for domain and realm.
+****************************************************************/
+
+void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
+ const char *server,
+ NTSTATUS result)
+{
+ add_failed_connection_entry(domain->name, server, result);
+ /* If this was the saf name for the last thing we talked to,
+ remove it. */
+ saf_delete(domain->name);
+ if (*domain->alt_name) {
+ add_failed_connection_entry(domain->alt_name, server, result);
+ saf_delete(domain->alt_name);
+ }
+}
/* Choose between anonymous or authenticated connections. We need to use
an authenticated connection if DCs have the RestrictAnonymous registry
@@ -75,9 +494,9 @@
static void cm_get_ipc_userpass(char **username, char **domain, char **password)
{
- *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
- *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
- *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+ *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
+ *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+ *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
if (*username && **username) {
@@ -106,7 +525,7 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
NTSTATUS result;
WERROR werr;
TALLOC_CTX *mem_ctx;
-
+ unsigned int orig_timeout;
fstring tmp;
char *p;
@@ -129,12 +548,21 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
result = cm_connect_netlogon(our_domain, &netlogon_pipe);
if (!NT_STATUS_IS_OK(result)) {
+ talloc_destroy(mem_ctx);
return False;
}
+ /* This call can take a long time - allow the server to time out.
+ 35 seconds should do it. */
+
+ orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
+
werr = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, our_domain->dcname,
domain->name, tmp);
+ /* And restore our original timeout. */
+ cli_set_timeout(netlogon_pipe->cli, orig_timeout);
+
talloc_destroy(mem_ctx);
if (!W_ERROR_IS_OK(werr)) {
@@ -186,6 +614,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
+ DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
+ controller, domain->name ));
+
machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
NULL);
@@ -215,7 +646,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
goto done;
}
- if ((*cli = cli_initialise(NULL)) == NULL) {
+ if ((*cli = cli_initialise()) == NULL) {
DEBUG(1, ("Could not cli_initialize\n"));
result = NT_STATUS_NO_MEMORY;
goto done;
@@ -327,10 +758,11 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
"[%s]\\[%s]\n", controller, global_myname(),
ipc_domain, ipc_username));
- if (cli_session_setup(*cli, ipc_username,
- ipc_password, strlen(ipc_password)+1,
- ipc_password, strlen(ipc_password)+1,
- ipc_domain)) {
+ if (NT_STATUS_IS_OK(cli_session_setup(
+ *cli, ipc_username,
+ ipc_password, strlen(ipc_password)+1,
+ ipc_password, strlen(ipc_password)+1,
+ ipc_domain))) {
/* Successful logon with given username. */
cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
goto session_setup_done;
@@ -342,7 +774,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
/* Fall back to anonymous connection, this might fail later */
- if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
+ if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
+ NULL, 0, ""))) {
DEBUG(5, ("Connected anonymously\n"));
cli_init_creds(*cli, "", "", "");
goto session_setup_done;
@@ -362,6 +795,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
/* cache the server name for later connections */
saf_store( domain->name, (*cli)->desthost );
+ if (domain->alt_name && (*cli)->use_kerberos) {
+ saf_store( domain->alt_name, (*cli)->desthost );
+ }
if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
@@ -399,7 +835,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
SAFE_FREE(ipc_password);
if (!NT_STATUS_IS_OK(result)) {
- add_failed_connection_entry(domain->name, controller, result);
+ winbind_add_failed_connection_entry(domain, controller, result);
if ((*cli) != NULL) {
cli_shutdown(*cli);
*cli = NULL;
@@ -409,11 +845,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
return result;
}
-struct dc_name_ip {
- fstring name;
- struct in_addr ip;
-};
-
static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name,
const char *dcname, struct in_addr ip,
struct dc_name_ip **dcs, int *num)
@@ -440,8 +871,10 @@ static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
{
*addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
- if (*addrs == NULL)
+ if (*addrs == NULL) {
+ *num = 0;
return False;
+ }
(*addrs)[*num].sin_family = PF_INET;
putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
@@ -581,21 +1014,63 @@ static BOOL receive_getdc_response(struct in_addr dc_ip,
convert an ip to a name
*******************************************************************/
-static BOOL dcip_to_name( const char *domainname, const char *realm,
- const DOM_SID *sid, struct in_addr ip, fstring name )
+static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip, fstring name )
{
struct ip_service ip_list;
ip_list.ip = ip;
ip_list.port = 0;
- /* try GETDC requests first */
+#ifdef WITH_ADS
+ /* For active directory servers, try to get the ldap server name.
+ None of these failures should be considered critical for now */
+
+ if (lp_security() == SEC_ADS) {
+ ADS_STRUCT *ads;
+
+ ads = ads_init(domain->alt_name, domain->name, NULL);
+ ads->auth.flags |= ADS_AUTH_NO_BIND;
+
+ if (ads_try_connect( ads, inet_ntoa(ip) ) ) {
+ /* We got a cldap packet. */
+ fstrcpy(name, ads->config.ldap_server_name);
+ namecache_store(name, 0x20, 1, &ip_list);
+
+ DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
+
+ if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
+ char *sitename = sitename_fetch(ads->config.realm);
+
+ /* We're going to use this KDC for this realm/domain.
+ If we are using sites, then force the krb5 libs
+ to use this KDC. */
+
+ create_local_private_krb5_conf_for_domain(domain->alt_name,
+ domain->name,
+ sitename,
+ ip);
+
+ SAFE_FREE(sitename);
+ /* Ensure we contact this DC also. */
+ saf_store( domain->name, name);
+ saf_store( domain->alt_name, name);
+ }
+
+ ads_destroy( &ads );
+ return True;
+ }
+
+ ads_destroy( &ads );
+ }
+#endif
+
+ /* try GETDC requests next */
- if (send_getdc_request(ip, domainname, sid)) {
+ if (send_getdc_request(ip, domain->name, &domain->sid)) {
int i;
smb_msleep(100);
for (i=0; i<5; i++) {
- if (receive_getdc_response(ip, domainname, name)) {
+ if (receive_getdc_response(ip, domain->name, name)) {
namecache_store(name, 0x20, 1, &ip_list);
return True;
}
@@ -605,35 +1080,10 @@ static BOOL dcip_to_name( const char *domainname, const char *realm,
/* try node status request */
- if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
+ if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
namecache_store(name, 0x20, 1, &ip_list);
return True;
}
-
-#ifdef WITH_ADS
- /* for active directory servers, try to get the ldap server name.
- None of these failure should be considered critical for now */
-
- if ( lp_security() == SEC_ADS )
- {
- ADS_STRUCT *ads;
-
- ads = ads_init( realm, domainname, NULL );
- ads->auth.flags |= ADS_AUTH_NO_BIND;
-
- if ( !ads_try_connect( ads, inet_ntoa(ip) ) ) {
- ads_destroy( &ads );
- return False;
- }
-
- fstrcpy(name, ads->config.ldap_server_name);
- namecache_store(name, 0x20, 1, &ip_list);
-
- ads_destroy( &ads );
- return True;
- }
-#endif
-
return False;
}
@@ -651,7 +1101,7 @@ static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
int iplist_size = 0;
int i;
BOOL is_our_domain;
-
+ enum security_types sec = (enum security_types)lp_security();
is_our_domain = strequal(domain->name, lp_workgroup());
@@ -664,14 +1114,50 @@ static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
return True;
}
- /* try standard netbios queries first */
+ if (sec == SEC_ADS) {
+ char *sitename = NULL;
+
+ /* We need to make sure we know the local site before
+ doing any DNS queries, as this will restrict the
+ get_sorted_dc_list() call below to only fetching
+ DNS records for the correct site. */
+
+ /* Find any DC to get the site record.
+ We deliberately don't care about the
+ return here. */
- get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
+ get_dc_name(domain->name, domain->alt_name, dcname, &ip);
- /* check for security = ads and use DNS if we can */
+ sitename = sitename_fetch(domain->alt_name);
+ if (sitename) {
- if ( iplist_size==0 && lp_security() == SEC_ADS )
- get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
+ /* Do the site-specific AD dns lookup first. */
+ get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
+
+ for ( i=0; i<iplist_size; i++ ) {
+ add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
+ ip_list[i].ip, dcs, num_dcs);
+ }
+
+ SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
+ iplist_size = 0;
+ }
+
+ /* Now we add DCs from the main AD dns lookup. */
+ get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
+
+ for ( i=0; i<iplist_size; i++ ) {
+ add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
+ ip_list[i].ip, dcs, num_dcs);
+ }
+ }
+
+ /* try standard netbios queries if no ADS */
+
+ if (iplist_size==0) {
+ get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
+ }
/* FIXME!! this is where we should re-insert the GETDC requests --jerry */
@@ -710,15 +1196,23 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
for (i=0; i<num_dcs; i++) {
- add_string_to_array(mem_ctx, dcs[i].name,
- &dcnames, &num_dcnames);
- add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
- &addrs, &num_addrs);
+ if (!add_string_to_array(mem_ctx, dcs[i].name,
+ &dcnames, &num_dcnames)) {
+ return False;
+ }
+ if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
+ &addrs, &num_addrs)) {
+ return False;
+ }
- add_string_to_array(mem_ctx, dcs[i].name,
- &dcnames, &num_dcnames);
- add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
- &addrs, &num_addrs);
+ if (!add_string_to_array(mem_ctx, dcs[i].name,
+ &dcnames, &num_dcnames)) {
+ return False;
+ }
+ if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
+ &addrs, &num_addrs)) {
+ return False;
+ }
}
if ((num_dcnames == 0) || (num_dcnames != num_addrs))
@@ -727,10 +1221,14 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
if ((addrs == NULL) || (dcnames == NULL))
return False;
- if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
+ /* 5 second timeout. */
+ if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
{
for (i=0; i<num_dcs; i++) {
- add_failed_connection_entry(domain->name,
+ DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
+ "domain %s address %s. Error was %s\n",
+ domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
+ winbind_add_failed_connection_entry(domain,
dcs[i].name, NT_STATUS_UNSUCCESSFUL);
}
return False;
@@ -745,13 +1243,12 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
}
/* Try to figure out the name */
- if (dcip_to_name( domain->name, domain->alt_name, &domain->sid,
- addr->sin_addr, dcname )) {
+ if (dcip_to_name( domain, addr->sin_addr, dcname )) {
return True;
}
/* We can not continue without the DC's name */
- add_failed_connection_entry(domain->name, dcs[fd_index].name,
+ winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
NT_STATUS_UNSUCCESSFUL);
goto again;
}
@@ -764,32 +1261,38 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
char *saf_servername = saf_fetch( domain->name );
int retries;
- if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
+ if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
+ SAFE_FREE(saf_servername);
+ set_domain_offline(domain);
return NT_STATUS_NO_MEMORY;
+ }
/* we have to check the server affinity cache here since
later we selecte a DC based on response time and not preference */
- if ( saf_servername )
- {
+ /* Check the negative connection cache
+ before talking to it. It going down may have
+ triggered the reconnection. */
+
+ if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
+
+ DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
+ saf_servername, domain->name ));
+
/* convert an ip address to a name */
- if ( is_ipaddress( saf_servername ) )
- {
+ if ( is_ipaddress( saf_servername ) ) {
fstring saf_name;
struct in_addr ip;
ip = *interpret_addr2( saf_servername );
- if (dcip_to_name( domain->name, domain->alt_name,
- &domain->sid, ip, saf_name )) {
+ if (dcip_to_name( domain, ip, saf_name )) {
fstrcpy( domain->dcname, saf_name );
} else {
- add_failed_connection_entry(
- domain->name, saf_servername,
+ winbind_add_failed_connection_entry(
+ domain, saf_servername,
NT_STATUS_UNSUCCESSFUL);
}
- }
- else
- {
+ } else {
fstrcpy( domain->dcname, saf_servername );
}
@@ -803,7 +1306,10 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- if ((strlen(domain->dcname) > 0)
+ DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
+ domain->dcname, domain->name ));
+
+ if (*domain->dcname
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
&& (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
{
@@ -811,11 +1317,19 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
int num_addrs = 0;
int dummy = 0;
- add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
- add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
+ if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
+ set_domain_offline(domain);
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
+ set_domain_offline(domain);
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
- if (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
- domain->online = False;
+ /* 5 second timeout. */
+ if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
fd = -1;
}
}
@@ -828,7 +1342,6 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
to true, if a "WINBINDD_OFFLINE" entry
is found in the winbindd cache. */
set_global_winbindd_state_offline();
- domain->online = False;
break;
}
@@ -846,7 +1359,10 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
/* We're changing state from offline to online. */
set_global_winbindd_state_online();
}
- domain->online = True;
+ set_domain_online(domain);
+ } else {
+ /* Ensure we setup the retry handler. */
+ set_domain_offline(domain);
}
talloc_destroy(mem_ctx);
@@ -857,18 +1373,40 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
void invalidate_cm_connection(struct winbindd_cm_conn *conn)
{
+ /* We're closing down a possibly dead
+ connection. Don't have impossibly long (10s) timeouts. */
+
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 1000); /* 1 second. */
+ }
+
if (conn->samr_pipe != NULL) {
- cli_rpc_pipe_close(conn->samr_pipe);
+ if (!cli_rpc_pipe_close(conn->samr_pipe)) {
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
+ }
+ }
conn->samr_pipe = NULL;
}
if (conn->lsa_pipe != NULL) {
- cli_rpc_pipe_close(conn->lsa_pipe);
+ if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
+ }
+ }
conn->lsa_pipe = NULL;
}
if (conn->netlogon_pipe != NULL) {
- cli_rpc_pipe_close(conn->netlogon_pipe);
+ if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
+ /* Ok, it must be dead. Drop timeout to 0.5 sec. */
+ if (conn->cli) {
+ cli_set_timeout(conn->cli, 500);
+ }
+ }
conn->netlogon_pipe = NULL;
}
@@ -898,37 +1436,71 @@ void close_conns_after_fork(void)
static BOOL connection_ok(struct winbindd_domain *domain)
{
if (domain->conn.cli == NULL) {
- DEBUG(8, ("Connection to %s for domain %s has NULL "
+ DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
"cli!\n", domain->dcname, domain->name));
return False;
}
if (!domain->conn.cli->initialised) {
- DEBUG(3, ("Connection to %s for domain %s was never "
+ DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
"initialised!\n", domain->dcname, domain->name));
return False;
}
if (domain->conn.cli->fd == -1) {
- DEBUG(3, ("Connection to %s for domain %s has died or was "
+ DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
"never started (fd == -1)\n",
domain->dcname, domain->name));
return False;
}
+ if (domain->online == False) {
+ DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
+ return False;
+ }
+
return True;
}
-
-/* Initialize a new connection up to the RPC BIND. */
-static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
+/* Initialize a new connection up to the RPC BIND.
+ Bypass online status check so always does network calls. */
+
+static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
{
- if (connection_ok(domain))
+ NTSTATUS result;
+
+ /* Internal connections never use the network. */
+ if (domain->internal) {
+ domain->initialized = True;
+ return NT_STATUS_OK;
+ }
+
+ if (connection_ok(domain)) {
+ if (!domain->initialized) {
+ set_dc_type_and_flags(domain);
+ }
return NT_STATUS_OK;
+ }
invalidate_cm_connection(&domain->conn);
- return cm_open_connection(domain, &domain->conn);
+ result = cm_open_connection(domain, &domain->conn);
+
+ if (NT_STATUS_IS_OK(result) && !domain->initialized) {
+ set_dc_type_and_flags(domain);
+ }
+
+ return result;
+}
+
+NTSTATUS init_dc_connection(struct winbindd_domain *domain)
+{
+ if (domain->initialized && !domain->online) {
+ /* We check for online status elsewhere. */
+ return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ }
+
+ return init_dc_connection_network(domain);
}
/******************************************************************************
@@ -939,35 +1511,26 @@ static NTSTATUS init_dc_connection(struct winbindd_domain *domain)
is native mode.
******************************************************************************/
-void set_dc_type_and_flags( struct winbindd_domain *domain )
+static void set_dc_type_and_flags( struct winbindd_domain *domain )
{
NTSTATUS result;
DS_DOMINFO_CTR ctr;
TALLOC_CTX *mem_ctx = NULL;
struct rpc_pipe_client *cli;
POLICY_HND pol;
-
+
char *domain_name = NULL;
char *dns_name = NULL;
- DOM_SID *dom_sid = NULL;
+ char *forest_name = NULL;
+ DOM_SID *dom_sid = NULL;
ZERO_STRUCT( ctr );
- domain->native_mode = False;
- domain->active_directory = False;
-
- if (domain->internal) {
- domain->initialized = True;
+ if (!connection_ok(domain)) {
return;
}
- result = init_dc_connection(domain);
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(5, ("set_dc_type_and_flags: Could not open a connection "
- "to %s: (%s)\n", domain->name, nt_errstr(result)));
- domain->initialized = True;
- return;
- }
+ DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
&result);
@@ -976,8 +1539,12 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
"PI_LSARPC_DS on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
- domain->initialized = True;
- return;
+
+ /* if this is just a non-AD domain we need to continue
+ * identifying so that we can in the end return with
+ * domain->initialized = True - gd */
+
+ goto no_lsarpc_ds;
}
result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
@@ -986,18 +1553,27 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
cli_rpc_pipe_close(cli);
if (!NT_STATUS_IS_OK(result)) {
- domain->initialized = True;
+ DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
+ "on domain %s failed: (%s)\n",
+ domain->name, nt_errstr(result)));
return;
}
if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
- !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
+ !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
domain->native_mode = True;
+ } else {
+ domain->native_mode = False;
+ }
+no_lsarpc_ds:
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
if (cli == NULL) {
- domain->initialized = True;
+ DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
+ "PI_LSARPC on domain %s: (%s)\n",
+ domain->name, nt_errstr(result)));
+ cli_rpc_pipe_close(cli);
return;
}
@@ -1017,23 +1593,27 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
to determine that the DC is active directory */
result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
12, &domain_name,
- &dns_name, NULL,
+ &dns_name, &forest_name,
NULL, &dom_sid);
}
if (NT_STATUS_IS_OK(result)) {
+ domain->active_directory = True;
+
if (domain_name)
fstrcpy(domain->name, domain_name);
if (dns_name)
fstrcpy(domain->alt_name, dns_name);
+ if ( forest_name )
+ fstrcpy(domain->forest_name, forest_name);
+
if (dom_sid)
sid_copy(&domain->sid, dom_sid);
-
- domain->active_directory = True;
} else {
-
+ domain->active_directory = False;
+
result = rpccli_lsa_open_policy(cli, mem_ctx, True,
SEC_RIGHTS_MAXIMUM_ALLOWED,
&pol);
@@ -1055,13 +1635,17 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
}
done:
+ DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
+ domain->name, domain->native_mode ? "" : "NOT "));
+
+ DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
+ domain->name, domain->active_directory ? "" : "NOT "));
+
cli_rpc_pipe_close(cli);
talloc_destroy(mem_ctx);
domain->initialized = True;
-
- return;
}
static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain,
@@ -1090,7 +1674,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
{
struct winbindd_cm_conn *conn;
- NTSTATUS result;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
fstring conn_pwd;
struct dcinfo *p_dcinfo;
@@ -1160,8 +1744,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
/* Fall back to schannel if it's a W2K pre-SP1 box. */
if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
+ /* If this call fails - conn->cli can now be NULL ! */
DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
- "for domain %s, trying anon\n", conn->cli->domain));
+ "for domain %s, trying anon\n", domain->name));
goto anonymous;
}
conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
@@ -1233,7 +1818,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
{
struct winbindd_cm_conn *conn;
- NTSTATUS result;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
fstring conn_pwd;
struct dcinfo *p_dcinfo;
@@ -1292,8 +1877,9 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
/* Fall back to schannel if it's a W2K pre-SP1 box. */
if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
+ /* If this call fails - conn->cli can now be NULL ! */
DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
- "for domain %s, trying anon\n", conn->cli->domain));
+ "for domain %s, trying anon\n", domain->name));
goto anonymous;
}
conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
@@ -1336,7 +1922,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
done:
if (!NT_STATUS_IS_OK(result)) {
invalidate_cm_connection(conn);
- return NT_STATUS_UNSUCCESSFUL;
+ return result;
}
*cli = conn->lsa_pipe;
diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c
index f5003ac8c63..0847ac9e271 100644
--- a/source/nsswitch/winbindd_cred_cache.c
+++ b/source/nsswitch/winbindd_cred_cache.c
@@ -1,9 +1,11 @@
/*
Unix SMB/CIFS implementation.
- Winbind daemon - krb5 credential cache funcions
+ Winbind daemon - krb5 credential cache functions
+ and in-memory cache functions.
- Copyright (C) Guenther Deschner 2005
+ Copyright (C) Guenther Deschner 2005-2006
+ Copyright (C) Jeremy Allison 2006
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
@@ -25,25 +27,15 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-#define MAX_CCACHES 100
+#define MAX_CCACHES 100
static struct WINBINDD_CCACHE_ENTRY *ccache_list;
-static TALLOC_CTX *mem_ctx;
+/****************************************************************
+ Find an entry by name.
+****************************************************************/
-const char *get_ccache_name_by_username(const char *username)
-{
- struct WINBINDD_CCACHE_ENTRY *entry;
-
- for (entry = ccache_list; entry; entry = entry->next) {
- if (strequal(entry->username, username)) {
- return entry->ccname;
- }
- }
- return NULL;
-}
-
-struct WINBINDD_CCACHE_ENTRY *get_ccache_by_username(const char *username)
+static struct WINBINDD_CCACHE_ENTRY *get_ccache_by_username(const char *username)
{
struct WINBINDD_CCACHE_ENTRY *entry;
@@ -55,6 +47,10 @@ struct WINBINDD_CCACHE_ENTRY *get_ccache_by_username(const char *username)
return NULL;
}
+/****************************************************************
+ How many do we have ?
+****************************************************************/
+
static int ccache_entry_count(void)
{
struct WINBINDD_CCACHE_ENTRY *entry;
@@ -66,49 +62,22 @@ static int ccache_entry_count(void)
return i;
}
-NTSTATUS remove_ccache_by_ccname(const char *ccname)
-{
- struct WINBINDD_CCACHE_ENTRY *entry;
+/****************************************************************
+ Do the work of refreshing the ticket.
+****************************************************************/
- for (entry = ccache_list; entry; entry = entry->next) {
- if (strequal(entry->ccname, ccname)) {
- DLIST_REMOVE(ccache_list, entry);
- TALLOC_FREE(entry->event); /* unregisters events */
-#ifdef HAVE_MUNLOCK
- if (entry->pass) {
- size_t len = strlen(entry->pass)+1;
-#ifdef DEBUG_PASSWORD
- DEBUG(10,("unlocking memory: %p\n", entry->pass));
-#endif
- memset(entry->pass, 0, len);
- if ((munlock(entry->pass, len)) == -1) {
- DEBUG(0,("failed to munlock memory: %s (%d)\n",
- strerror(errno), errno));
- return map_nt_error_from_unix(errno);
- }
-#ifdef DEBUG_PASSWORD
- DEBUG(10,("munlocked memory: %p\n", entry->pass));
-#endif
- }
-#endif /* HAVE_MUNLOCK */
- TALLOC_FREE(entry);
- DEBUG(10,("remove_ccache_by_ccname: removed ccache %s\n", ccname));
- return NT_STATUS_OK;
- }
- }
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-}
-
-static void krb5_ticket_refresh_handler(struct timed_event *te,
+static void krb5_ticket_refresh_handler(struct event_context *event_ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data)
{
struct WINBINDD_CCACHE_ENTRY *entry =
talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY);
+#ifdef HAVE_KRB5
int ret;
time_t new_start;
- struct timeval t;
-
+ struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr;
+#endif
DEBUG(10,("krb5_ticket_refresh_handler called\n"));
DEBUGADD(10,("event called for: %s, %s\n", entry->ccname, entry->username));
@@ -120,12 +89,12 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
/* Kinit again if we have the user password and we can't renew the old
* tgt anymore */
- if ((entry->renew_until < time(NULL)) && (entry->pass != NULL)) {
+ if ((entry->renew_until < time(NULL)) && cred_ptr && cred_ptr->pass) {
set_effective_uid(entry->uid);
ret = kerberos_kinit_password_ext(entry->principal_name,
- entry->pass,
+ cred_ptr->pass,
0, /* hm, can we do time correction here ? */
&entry->refresh_time,
&entry->renew_until,
@@ -136,12 +105,14 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
gain_root_privilege();
if (ret) {
- DEBUG(3,("could not re-kinit: %s\n", error_message(ret)));
+ DEBUG(3,("krb5_ticket_refresh_handler: could not re-kinit: %s\n",
+ error_message(ret)));
TALLOC_FREE(entry->event);
return;
}
- DEBUG(10,("successful re-kinit for: %s in ccache: %s\n",
+ DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit "
+ "for: %s in ccache: %s\n",
entry->principal_name, entry->ccname));
new_start = entry->refresh_time;
@@ -158,17 +129,25 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
gain_root_privilege();
if (ret) {
- DEBUG(3,("could not renew tickets: %s\n", error_message(ret)));
+ DEBUG(3,("krb5_ticket_refresh_handler: could not renew tickets: %s\n",
+ error_message(ret)));
/* maybe we are beyond the renewing window */
+
+ /* avoid breaking the renewal chain: retry in lp_winbind_cache_time()
+ * seconds when the KDC was not available right now. */
+
+ if (ret == KRB5_KDC_UNREACH) {
+ new_start = time(NULL) + MAX(30, lp_winbind_cache_time());
+ goto done;
+ }
+
return;
}
done:
- t = timeval_set(new_start, 0);
-
- entry->event = add_timed_event(mem_ctx,
- t,
+ entry->event = event_add_timed(winbind_event_context(), entry,
+ timeval_set(new_start, 0),
"krb5_ticket_refresh_handler",
krb5_ticket_refresh_handler,
entry);
@@ -176,152 +155,563 @@ done:
#endif
}
+/****************************************************************
+ Do the work of regaining a ticket when coming from offline auth.
+****************************************************************/
+
+static void krb5_ticket_gain_handler(struct event_context *event_ctx,
+ struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry =
+ talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY);
+#ifdef HAVE_KRB5
+ int ret;
+ time_t new_start;
+ struct timeval t;
+ struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr;
+ struct winbindd_domain *domain = NULL;
+#endif
+
+ DEBUG(10,("krb5_ticket_gain_handler called\n"));
+ DEBUGADD(10,("event called for: %s, %s\n", entry->ccname, entry->username));
+
+ TALLOC_FREE(entry->event);
+
+#ifdef HAVE_KRB5
+
+ if (!cred_ptr || !cred_ptr->pass) {
+ DEBUG(10,("krb5_ticket_gain_handler: no memory creds\n"));
+ return;
+ }
+
+ if ((domain = find_domain_from_name(entry->realm)) == NULL) {
+ DEBUG(0,("krb5_ticket_gain_handler: unknown domain\n"));
+ return;
+ }
+
+ if (domain->online) {
+
+ set_effective_uid(entry->uid);
+
+ ret = kerberos_kinit_password_ext(entry->principal_name,
+ cred_ptr->pass,
+ 0, /* hm, can we do time correction here ? */
+ &entry->refresh_time,
+ &entry->renew_until,
+ entry->ccname,
+ False, /* no PAC required anymore */
+ True,
+ WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
+ gain_root_privilege();
+
+ if (ret) {
+ DEBUG(3,("krb5_ticket_gain_handler: could not kinit: %s\n",
+ error_message(ret)));
+ goto retry_later;
+ }
+
+ DEBUG(10,("krb5_ticket_gain_handler: successful kinit for: %s in ccache: %s\n",
+ entry->principal_name, entry->ccname));
+
+ new_start = entry->refresh_time;
+
+ goto got_ticket;
+ }
+
+ retry_later:
+
+ entry->event = event_add_timed(winbind_event_context(), entry,
+ timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0),
+ "krb5_ticket_gain_handler",
+ krb5_ticket_gain_handler,
+ entry);
+
+ return;
+
+ got_ticket:
+
+#if 0 /* TESTING */
+ t = timeval_set(time(NULL) + 30, 0);
+#else
+ t = timeval_set(new_start, 0);
+#endif /* TESTING */
+
+ entry->event = event_add_timed(winbind_event_context(), entry,
+ t,
+ "krb5_ticket_refresh_handler",
+ krb5_ticket_refresh_handler,
+ entry);
+
+ return;
+#endif
+}
+
+/****************************************************************
+ Check if an ccache entry exists.
+****************************************************************/
+
+BOOL ccache_entry_exists(const char *username)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username);
+ return (entry != NULL);
+}
+
+/****************************************************************
+ Ensure we're changing the correct entry.
+****************************************************************/
+
+BOOL ccache_entry_identical(const char *username, uid_t uid, const char *ccname)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username);
+
+ if (!entry) {
+ return False;
+ }
+
+ if (entry->uid != uid) {
+ DEBUG(0,("cache_entry_identical: uid's differ: %u != %u\n",
+ (unsigned int)entry->uid, (unsigned int)uid ));
+ return False;
+ }
+ if (!strcsequal(entry->ccname, ccname)) {
+ DEBUG(0,("cache_entry_identical: ccnames differ: (cache) %s != (client) %s\n",
+ entry->ccname, ccname));
+ return False;
+ }
+ return True;
+}
+
NTSTATUS add_ccache_to_list(const char *princ_name,
const char *ccname,
const char *service,
const char *username,
- const char *sid_string,
- const char *pass,
+ const char *realm,
uid_t uid,
time_t create_time,
time_t ticket_end,
time_t renew_until,
- BOOL schedule_refresh_event)
+ BOOL postponed_request)
{
- struct WINBINDD_CCACHE_ENTRY *new_entry = NULL;
- struct WINBINDD_CCACHE_ENTRY *old_entry = NULL;
- NTSTATUS status;
+ struct WINBINDD_CCACHE_ENTRY *entry = NULL;
- if ((username == NULL && sid_string == NULL && princ_name == NULL) ||
- ccname == NULL) {
+ if ((username == NULL && princ_name == NULL) || ccname == NULL || uid < 0) {
return NT_STATUS_INVALID_PARAMETER;
}
- status = init_ccache_list();
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (mem_ctx == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
if (ccache_entry_count() + 1 > MAX_CCACHES) {
DEBUG(10,("add_ccache_to_list: max number of ccaches reached\n"));
return NT_STATUS_NO_MORE_ENTRIES;
}
- /* get rid of old entries */
- old_entry = get_ccache_by_username(username);
- if (old_entry) {
- status = remove_ccache_by_ccname(old_entry->ccname);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("add_ccache_to_list: failed to delete old ccache entry\n"));
- return status;
+ /* Reference count old entries */
+ entry = get_ccache_by_username(username);
+ if (entry) {
+ /* Check cached entries are identical. */
+ if (!ccache_entry_identical(username, uid, ccname)) {
+ return NT_STATUS_INVALID_PARAMETER;
}
+ entry->ref_count++;
+ DEBUG(10,("add_ccache_to_list: ref count on entry %s is now %d\n",
+ username, entry->ref_count));
+ /* FIXME: in this case we still might want to have a krb5 cred
+ * event handler created - gd*/
+ return NT_STATUS_OK;
}
- new_entry = TALLOC_P(mem_ctx, struct WINBINDD_CCACHE_ENTRY);
- if (new_entry == NULL) {
+ entry = TALLOC_P(NULL, struct WINBINDD_CCACHE_ENTRY);
+ if (!entry) {
return NT_STATUS_NO_MEMORY;
}
- ZERO_STRUCTP(new_entry);
+ ZERO_STRUCTP(entry);
if (username) {
- new_entry->username = talloc_strdup(mem_ctx, username);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->username);
- }
- if (sid_string) {
- new_entry->sid_string = talloc_strdup(mem_ctx, sid_string);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->sid_string);
+ entry->username = talloc_strdup(entry, username);
+ if (!entry->username) {
+ goto no_mem;
+ }
}
if (princ_name) {
- new_entry->principal_name = talloc_strdup(mem_ctx, princ_name);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->principal_name);
+ entry->principal_name = talloc_strdup(entry, princ_name);
+ if (!entry->principal_name) {
+ goto no_mem;
+ }
}
if (service) {
- new_entry->service = talloc_strdup(mem_ctx, service);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->service);
+ entry->service = talloc_strdup(entry, service);
+ if (!entry->service) {
+ goto no_mem;
+ }
+ }
+
+ entry->ccname = talloc_strdup(entry, ccname);
+ if (!entry->ccname) {
+ goto no_mem;
}
- if (schedule_refresh_event && pass) {
-#ifdef HAVE_MLOCK
- size_t len = strlen(pass)+1;
-
- new_entry->pass = TALLOC_ZERO(mem_ctx, len);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
-
+ entry->realm = talloc_strdup(entry, realm);
+ if (!entry->realm) {
+ goto no_mem;
+ }
+
+ entry->create_time = create_time;
+ entry->renew_until = renew_until;
+ entry->uid = uid;
+ entry->ref_count = 1;
+
+ if (lp_winbind_refresh_tickets() && renew_until > 0) {
+ if (postponed_request) {
+ entry->event = event_add_timed(winbind_event_context(), entry,
+ timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0),
+ "krb5_ticket_gain_handler",
+ krb5_ticket_gain_handler,
+ entry);
+ } else {
+ entry->event = event_add_timed(winbind_event_context(), entry,
+ timeval_set((ticket_end - 1), 0),
+ "krb5_ticket_refresh_handler",
+ krb5_ticket_refresh_handler,
+ entry);
+ }
+
+ if (!entry->event) {
+ goto no_mem;
+ }
+
+ DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n"));
+ }
+
+ DLIST_ADD(ccache_list, entry);
+
+ DEBUG(10,("add_ccache_to_list: added ccache [%s] for user [%s] to the list\n", ccname, username));
+
+ return NT_STATUS_OK;
+
+ no_mem:
+
+ TALLOC_FREE(entry);
+ return NT_STATUS_NO_MEMORY;
+}
+
+/*******************************************************************
+ Remove a WINBINDD_CCACHE_ENTRY entry and the krb5 ccache if no longer referenced.
+*******************************************************************/
+
+NTSTATUS remove_ccache(const char *username)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username);
+ NTSTATUS status;
+#ifdef HAVE_KRB5
+ krb5_error_code ret;
+#endif
+
+ if (!entry) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (entry->ref_count <= 0) {
+ DEBUG(0,("remove_ccache: logic error. ref count for user %s = %d\n",
+ username, entry->ref_count));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry->ref_count--;
+
+ if (entry->ref_count > 0) {
+ DEBUG(10,("remove_ccache: entry %s ref count now %d\n",
+ username, entry->ref_count ));
+ return NT_STATUS_OK;
+ }
+
+ /* no references any more */
+
+ DLIST_REMOVE(ccache_list, entry);
+ TALLOC_FREE(entry->event); /* unregisters events */
+
+#ifdef HAVE_KRB5
+ ret = ads_kdestroy(entry->ccname);
+
+ /* we ignore the error when there has been no credential cache */
+ if (ret == KRB5_FCC_NOFILE) {
+ ret = 0;
+ } else if (ret) {
+ DEBUG(0,("remove_ccache: failed to destroy user krb5 ccache %s with: %s\n",
+ entry->ccname, error_message(ret)));
+ } else {
+ DEBUG(10,("remove_ccache: successfully destroyed krb5 ccache %s for user %s\n",
+ entry->ccname, username));
+ }
+ status = krb5_to_nt_status(ret);
+#endif
+
+ TALLOC_FREE(entry);
+ DEBUG(10,("remove_ccache: removed ccache for user %s\n", username));
+
+ return status;
+}
+
+/*******************************************************************
+ In memory credentials cache code.
+*******************************************************************/
+
+static struct WINBINDD_MEMORY_CREDS *memory_creds_list;
+
+/***********************************************************
+ Find an entry on the list by name.
+***********************************************************/
+
+struct WINBINDD_MEMORY_CREDS *find_memory_creds_by_name(const char *username)
+{
+ struct WINBINDD_MEMORY_CREDS *p;
+
+ for (p = memory_creds_list; p; p = p->next) {
+ if (strequal(p->username, username)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+/***********************************************************
+ Store the required creds and mlock them.
+***********************************************************/
+
+static NTSTATUS store_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp, const char *pass)
+{
+#if !defined(HAVE_MLOCK)
+ return NT_STATUS_OK;
+#else
+ int psize = getpagesize();
+
+ /* new_entry->nt_hash is the base pointer for the block
+ of memory pointed into by new_entry->lm_hash and
+ new_entry->pass (if we're storing plaintext). */
+
+ memcredp->len = NT_HASH_LEN + LM_HASH_LEN;
+ if (pass) {
+ memcredp->len += strlen(pass)+1;
+ }
+
+ /* On non-linux platforms, mlock()'d memory must be aligned */
+
+ memcredp->nt_hash = SMB_MEMALIGN_ARRAY(unsigned char, psize,
+ memcredp->len);
+ if (!memcredp->nt_hash) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ memset( memcredp->nt_hash, 0x0, memcredp->len );
+
+ memcredp->lm_hash = memcredp->nt_hash + NT_HASH_LEN;
+
#ifdef DEBUG_PASSWORD
- DEBUG(10,("mlocking memory: %p\n", new_entry->pass));
+ DEBUG(10,("mlocking memory: %p\n", memcredp->nt_hash));
#endif
- if ((mlock(new_entry->pass, len)) == -1) {
- DEBUG(0,("failed to mlock memory: %s (%d)\n",
- strerror(errno), errno));
- return map_nt_error_from_unix(errno);
- }
-
+ if ((mlock(memcredp->nt_hash, memcredp->len)) == -1) {
+ DEBUG(0,("failed to mlock memory: %s (%d)\n",
+ strerror(errno), errno));
+ return map_nt_error_from_unix(errno);
+ }
+
#ifdef DEBUG_PASSWORD
- DEBUG(10,("mlocked memory: %p\n", new_entry->pass));
+ DEBUG(10,("mlocked memory: %p\n", memcredp->nt_hash));
#endif
- memcpy(new_entry->pass, pass, len);
+
+ /* Create and store the password hashes. */
+ E_md4hash(pass, memcredp->nt_hash);
+ E_deshash(pass, memcredp->lm_hash);
+
+ if (pass) {
+ memcredp->pass = (char *)memcredp->lm_hash + LM_HASH_LEN;
+ memcpy(memcredp->pass, pass, memcredp->len - NT_HASH_LEN - LM_HASH_LEN);
+ }
+
+ return NT_STATUS_OK;
+#endif
+}
+
+/***********************************************************
+ Destroy existing creds.
+***********************************************************/
+
+static NTSTATUS delete_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp)
+{
+#if !defined(HAVE_MUNLOCK)
+ return NT_STATUS_OK;
#else
- new_entry->pass = talloc_strdup(mem_ctx, pass);
- NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
-#endif /* HAVE_MLOCK */
+ if (munlock(memcredp->nt_hash, memcredp->len) == -1) {
+ DEBUG(0,("failed to munlock memory: %s (%d)\n",
+ strerror(errno), errno));
+ return map_nt_error_from_unix(errno);
}
+ memset(memcredp->nt_hash, '\0', memcredp->len);
+ SAFE_FREE(memcredp->nt_hash);
+ memcredp->nt_hash = NULL;
+ memcredp->lm_hash = NULL;
+ memcredp->pass = NULL;
+ memcredp->len = 0;
+ return NT_STATUS_OK;
+#endif
+}
- new_entry->create_time = create_time;
- new_entry->renew_until = renew_until;
- new_entry->ccname = talloc_strdup(mem_ctx, ccname);
- if (new_entry->ccname == NULL) {
- return NT_STATUS_NO_MEMORY;
+/***********************************************************
+ Replace the required creds with new ones (password change).
+***********************************************************/
+
+static NTSTATUS winbindd_replace_memory_creds_internal(struct WINBINDD_MEMORY_CREDS *memcredp,
+ const char *pass)
+{
+ NTSTATUS status = delete_memory_creds(memcredp);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- new_entry->uid = uid;
+ return store_memory_creds(memcredp, pass);
+}
+/*************************************************************
+ Store credentials in memory in a list.
+*************************************************************/
- if (schedule_refresh_event && renew_until > 0) {
+static NTSTATUS winbindd_add_memory_creds_internal(const char *username, uid_t uid, const char *pass)
+{
+ /* Shortcut to ensure we don't store if no mlock. */
+#if !defined(HAVE_MLOCK) || !defined(HAVE_MUNLOCK)
+ return NT_STATUS_OK;
+#else
+ NTSTATUS status;
+ struct WINBINDD_MEMORY_CREDS *memcredp = find_memory_creds_by_name(username);
- struct timeval t = timeval_set((ticket_end -1 ), 0);
+ if (uid == (uid_t)-1) {
+ DEBUG(0,("winbindd_add_memory_creds_internal: invalid uid for user %s.\n",
+ username ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- new_entry->event = add_timed_event(mem_ctx,
- t,
- "krb5_ticket_refresh_handler",
- krb5_ticket_refresh_handler,
- new_entry);
+ if (memcredp) {
+ /* Already exists. Increment the reference count and replace stored creds. */
+ if (uid != memcredp->uid) {
+ DEBUG(0,("winbindd_add_memory_creds_internal: uid %u for user %s doesn't "
+ "match stored uid %u. Replacing.\n",
+ (unsigned int)uid, username, (unsigned int)memcredp->uid ));
+ memcredp->uid = uid;
+ }
+ memcredp->ref_count++;
+ DEBUG(10,("winbindd_add_memory_creds_internal: ref count for user %s is now %d\n",
+ username, memcredp->ref_count ));
+ return winbindd_replace_memory_creds_internal(memcredp, pass);
}
- DLIST_ADD(ccache_list, new_entry);
+ memcredp = TALLOC_ZERO_P(NULL, struct WINBINDD_MEMORY_CREDS);
+ if (!memcredp) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ memcredp->username = talloc_strdup(memcredp, username);
+ if (!memcredp->username) {
+ talloc_destroy(memcredp);
+ return NT_STATUS_NO_MEMORY;
+ }
- DEBUG(10,("add_ccache_to_list: added ccache [%s] for user [%s] to the list\n", ccname, username));
+ status = store_memory_creds(memcredp, pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_destroy(memcredp);
+ return status;
+ }
+
+ memcredp->uid = uid;
+ memcredp->ref_count = 1;
+ DLIST_ADD(memory_creds_list, memcredp);
+
+ DEBUG(10,("winbindd_add_memory_creds_internal: added entry for user %s\n",
+ username ));
return NT_STATUS_OK;
+#endif
}
-NTSTATUS destroy_ccache_list(void)
+/*************************************************************
+ Store users credentials in memory. If we also have a
+ struct WINBINDD_CCACHE_ENTRY for this username with a
+ refresh timer, then store the plaintext of the password
+ and associate the new credentials with the struct WINBINDD_CCACHE_ENTRY.
+*************************************************************/
+
+NTSTATUS winbindd_add_memory_creds(const char *username, uid_t uid, const char *pass)
{
-#ifdef HAVE_MUNLOCKALL
- if ((munlockall()) == -1) {
- DEBUG(0,("failed to unlock memory: %s (%d)\n",
- strerror(errno), errno));
- return map_nt_error_from_unix(errno);
+ struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username);
+ NTSTATUS status;
+
+ status = winbindd_add_memory_creds_internal(username, uid, pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (entry) {
+ struct WINBINDD_MEMORY_CREDS *memcredp = find_memory_creds_by_name(username);
+ if (memcredp) {
+ entry->cred_ptr = memcredp;
+ }
}
-#endif /* HAVE_MUNLOCKALL */
- return talloc_destroy(mem_ctx) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ return status;
}
-NTSTATUS init_ccache_list(void)
+/*************************************************************
+ Decrement the in-memory ref count - delete if zero.
+*************************************************************/
+
+NTSTATUS winbindd_delete_memory_creds(const char *username)
{
- if (ccache_list) {
- return NT_STATUS_OK;
+ struct WINBINDD_MEMORY_CREDS *memcredp = find_memory_creds_by_name(username);
+ struct WINBINDD_CCACHE_ENTRY *entry = get_ccache_by_username(username);
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (!memcredp) {
+ DEBUG(10,("winbindd_delete_memory_creds: unknown user %s\n",
+ username ));
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- mem_ctx = talloc_init("winbindd_ccache_krb5_handling");
- if (mem_ctx == NULL) {
- return NT_STATUS_NO_MEMORY;
+ if (memcredp->ref_count <= 0) {
+ DEBUG(0,("winbindd_delete_memory_creds: logic error. ref count for user %s = %d\n",
+ username, memcredp->ref_count));
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- ZERO_STRUCTP(ccache_list);
+ memcredp->ref_count--;
+ if (memcredp->ref_count <= 0) {
+ delete_memory_creds(memcredp);
+ DLIST_REMOVE(memory_creds_list, memcredp);
+ talloc_destroy(memcredp);
+ DEBUG(10,("winbindd_delete_memory_creds: deleted entry for user %s\n",
+ username));
+ } else {
+ DEBUG(10,("winbindd_delete_memory_creds: entry for user %s ref_count now %d\n",
+ username, memcredp->ref_count));
+ }
- return NT_STATUS_OK;
+ if (entry) {
+ entry->cred_ptr = NULL; /* Ensure we have no dangling references to this. */
+ }
+ return status;
+}
+
+/***********************************************************
+ Replace the required creds with new ones (password change).
+***********************************************************/
+
+NTSTATUS winbindd_replace_memory_creds(const char *username, const char *pass)
+{
+ struct WINBINDD_MEMORY_CREDS *memcredp = find_memory_creds_by_name(username);
+
+ if (!memcredp) {
+ DEBUG(10,("winbindd_replace_memory_creds: unknown user %s\n",
+ username ));
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ DEBUG(10,("winbindd_replace_memory_creds: replaced creds for user %s\n",
+ username ));
+
+ return winbindd_replace_memory_creds_internal(memcredp, pass);
}
diff --git a/source/nsswitch/winbindd_creds.c b/source/nsswitch/winbindd_creds.c
index 414dd24af9e..f11b80909bf 100644
--- a/source/nsswitch/winbindd_creds.c
+++ b/source/nsswitch/winbindd_creds.c
@@ -31,12 +31,13 @@ NTSTATUS winbindd_get_creds(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
NET_USER_INFO_3 **info3,
- const uint8 *cached_nt_pass[NT_HASH_LEN])
+ const uint8 *cached_nt_pass[NT_HASH_LEN],
+ const uint8 *cred_salt[NT_HASH_LEN])
{
NET_USER_INFO_3 *info;
NTSTATUS status;
- status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass);
+ status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass, cred_salt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -79,7 +80,7 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain,
/* do lookup ourself */
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (!lookup_cached_name(mem_ctx,
domain->name,
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index 6206bb256f0..edb4fa504b1 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -34,6 +34,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+extern BOOL override_logfile;
+
/* Read some data from a client connection */
static void child_read_request(struct winbindd_cli_state *state)
@@ -108,7 +110,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
void (*continuation)(void *private_data, BOOL success),
void *private_data)
{
- struct winbindd_async_request *state, *tmp;
+ struct winbindd_async_request *state;
SMB_ASSERT(continuation != NULL);
@@ -127,7 +129,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
state->continuation = continuation;
state->private_data = private_data;
- DLIST_ADD_END(child->requests, state, tmp);
+ DLIST_ADD_END(child->requests, state, struct winbindd_async_request *);
schedule_async_request(child);
@@ -190,7 +192,12 @@ static void async_reply_recv(void *private_data, BOOL success)
if (!success) {
DEBUG(5, ("Could not receive async reply\n"));
+
+ cache_cleanup_response(child->pid);
+ DLIST_REMOVE(child->requests, state);
+
state->response->result = WINBINDD_ERROR;
+ state->continuation(state->private_data, False);
return;
}
@@ -236,7 +243,6 @@ static void schedule_async_request(struct winbindd_child *child)
sizeof(*request->request),
async_main_request_sent, request);
- talloc_destroy(child->mem_ctx);
return;
}
@@ -345,6 +351,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" },
{ WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" },
+ { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" },
{ WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" },
{ WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" },
{ WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" },
@@ -352,21 +359,27 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" },
{ WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" },
{ WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" },
+ { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" },
+ { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" },
{ WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
{ WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
{ WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
+ { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" },
{ WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" },
{ WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" },
{ WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" },
{ WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" },
{ WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" },
{ WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" },
- { WINBINDD_DUAL_IDMAPSET, winbindd_dual_idmapset, "DUAL_IDMAPSET" },
+ { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" },
+ { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" },
+ { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" },
{ WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" },
{ WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" },
{ WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" },
{ WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" },
{ WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" },
+ { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" },
/* End of list */
{ WINBINDD_NUM_CMDS, NULL, "NONE" }
@@ -451,10 +464,23 @@ void winbind_child_died(pid_t pid)
schedule_async_request(child);
}
-/* Forward the online/offline messages to our children. */
-void winbind_msg_offline(int msg_type, struct process_id src, void *buf, size_t len)
+/* Ensure any negative cache entries with the netbios or realm names are removed. */
+
+void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
+{
+ flush_negative_conn_cache_for_domain(domain->name);
+ if (*domain->alt_name) {
+ flush_negative_conn_cache_for_domain(domain->alt_name);
+ }
+}
+
+/* Set our domains as offline and forward the offline message to our children. */
+
+void winbind_msg_offline(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
struct winbindd_child *child;
+ struct winbindd_domain *domain;
DEBUG(10,("winbind_msg_offline: got offline message.\n"));
@@ -469,17 +495,44 @@ void winbind_msg_offline(int msg_type, struct process_id src, void *buf, size_t
return;
}
+ /* Set all our domains as offline. */
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if (domain->internal) {
+ continue;
+ }
+ DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name));
+ set_domain_offline(domain);
+ }
+
for (child = children; child != NULL; child = child->next) {
- DEBUG(10,("winbind_msg_offline: sending message to pid %u.\n",
- (unsigned int)child->pid ));
- message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_OFFLINE, NULL, 0, False);
+ /* Don't send message to idmap child. */
+ if (!child->domain || (child == idmap_child())) {
+ continue;
+ }
+
+ /* Or internal domains (this should not be possible....) */
+ if (child->domain->internal) {
+ continue;
+ }
+
+ /* Each winbindd child should only process requests for one domain - make sure
+ we only set it online / offline for that domain. */
+
+ DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n",
+ (unsigned int)child->pid, domain->name ));
+
+ message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_OFFLINE, child->domain->name,
+ strlen(child->domain->name)+1, False);
}
}
-/* Forward the online/offline messages to our children. */
-void winbind_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+/* Set our domains as online and forward the online message to our children. */
+
+void winbind_msg_online(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
struct winbindd_child *child;
+ struct winbindd_domain *domain;
DEBUG(10,("winbind_msg_online: got online message.\n"));
@@ -491,15 +544,45 @@ void winbind_msg_online(int msg_type, struct process_id src, void *buf, size_t l
/* Set our global state as online. */
set_global_winbindd_state_online();
+ smb_nscd_flush_user_cache();
+ smb_nscd_flush_group_cache();
+
+ /* Set all our domains as online. */
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if (domain->internal) {
+ continue;
+ }
+ DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name));
+
+ winbindd_flush_negative_conn_cache(domain);
+ set_domain_online_request(domain);
+ }
+
for (child = children; child != NULL; child = child->next) {
- DEBUG(10,("winbind_msg_online: sending message to pid %u.\n",
- (unsigned int)child->pid ));
- message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_ONLINE, NULL, 0, False);
+ /* Don't send message to idmap child. */
+ if (!child->domain || (child == idmap_child())) {
+ continue;
+ }
+
+ /* Or internal domains (this should not be possible....) */
+ if (child->domain->internal) {
+ continue;
+ }
+
+ /* Each winbindd child should only process requests for one domain - make sure
+ we only set it online / offline for that domain. */
+
+ DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n",
+ (unsigned int)child->pid, child->domain->name ));
+
+ message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_ONLINE, child->domain->name,
+ strlen(child->domain->name)+1, False);
}
}
/* Forward the online/offline messages to our children. */
-void winbind_msg_onlinestatus(int msg_type, struct process_id src, void *buf, size_t len)
+void winbind_msg_onlinestatus(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
struct winbindd_child *child;
@@ -518,12 +601,14 @@ void winbind_msg_onlinestatus(int msg_type, struct process_id src, void *buf, si
}
-static void account_lockout_policy_handler(struct timed_event *te,
+static void account_lockout_policy_handler(struct event_context *ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data)
{
- struct winbindd_child *child = private_data;
-
+ struct winbindd_child *child =
+ (struct winbindd_child *)private_data;
+ TALLOC_CTX *mem_ctx = NULL;
struct winbindd_methods *methods;
SAM_UNK_INFO_12 lockout_policy;
NTSTATUS result;
@@ -536,13 +621,21 @@ static void account_lockout_policy_handler(struct timed_event *te,
methods = child->domain->methods;
- result = methods->lockout_policy(child->domain, child->mem_ctx, &lockout_policy);
+ mem_ctx = talloc_init("account_lockout_policy_handler ctx");
+ if (!mem_ctx) {
+ result = NT_STATUS_NO_MEMORY;
+ } else {
+ result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy);
+ }
+
+ talloc_destroy(mem_ctx);
+
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("account_lockout_policy_handler: failed to call lockout_policy\n"));
- return;
+ DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n",
+ nt_errstr(result)));
}
- child->lockout_policy_event = add_timed_event(child->mem_ctx,
+ child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL,
timeval_current_ofs(3600, 0),
"account_lockout_policy_handler",
account_lockout_policy_handler,
@@ -551,11 +644,17 @@ static void account_lockout_policy_handler(struct timed_event *te,
/* Deal with a request to go offline. */
-static void child_msg_offline(int msg_type, struct process_id src, void *buf, size_t len)
+static void child_msg_offline(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
struct winbindd_domain *domain;
+ const char *domainname = (const char *)buf;
- DEBUG(5,("child_msg_offline received.\n"));
+ if (buf == NULL || len == 0) {
+ return;
+ }
+
+ DEBUG(5,("child_msg_offline received for domain %s.\n", domainname));
if (!lp_winbind_offline_logon()) {
DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
@@ -568,21 +667,32 @@ static void child_msg_offline(int msg_type, struct process_id src, void *buf, si
return;
}
- /* Mark all our domains as offline. */
+ /* Mark the requested domain offline. */
for (domain = domain_list(); domain; domain = domain->next) {
- DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
- domain->online = False;
+ if (domain->internal) {
+ continue;
+ }
+ if (strequal(domain->name, domainname)) {
+ DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
+ set_domain_offline(domain);
+ }
}
}
/* Deal with a request to go online. */
-static void child_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+static void child_msg_online(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
struct winbindd_domain *domain;
+ const char *domainname = (const char *)buf;
+
+ if (buf == NULL || len == 0) {
+ return;
+ }
- DEBUG(5,("child_msg_online received.\n"));
+ DEBUG(5,("child_msg_online received for domain %s.\n", domainname));
if (!lp_winbind_offline_logon()) {
DEBUG(10,("child_msg_online: rejecting online message.\n"));
@@ -592,16 +702,18 @@ static void child_msg_online(int msg_type, struct process_id src, void *buf, siz
/* Set our global state as online. */
set_global_winbindd_state_online();
- smb_nscd_flush_user_cache();
- smb_nscd_flush_group_cache();
-
- /* Mark everything online - delete any negative cache entries
- to force an immediate reconnect. */
+ /* Try and mark everything online - delete any negative cache entries
+ to force a reconnect now. */
for (domain = domain_list(); domain; domain = domain->next) {
- DEBUG(5,("child_msg_online: marking %s online.\n", domain->name));
- domain->online = True;
- check_negative_conn_cache_timeout(domain->name, domain->dcname, 0);
+ if (domain->internal) {
+ continue;
+ }
+ if (strequal(domain->name, domainname)) {
+ DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name));
+ winbindd_flush_negative_conn_cache(domain);
+ set_domain_online_request(domain);
+ }
}
}
@@ -611,7 +723,7 @@ static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
char *buf = NULL;
if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
- get_global_winbindd_state_online() ?
+ get_global_winbindd_state_offline() ?
"Offline":"Online")) == NULL) {
return NULL;
}
@@ -632,7 +744,8 @@ static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
return buf;
}
-static void child_msg_onlinestatus(int msg_type, struct process_id src, void *buf, size_t len)
+static void child_msg_onlinestatus(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
TALLOC_CTX *mem_ctx;
const char *message;
@@ -667,7 +780,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
{
int fdpair[2];
struct winbindd_cli_state state;
- extern BOOL override_logfile;
+ struct winbindd_domain *domain;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
DEBUG(0, ("Could not open child pipe: %s\n",
@@ -676,7 +789,10 @@ static BOOL fork_domain_child(struct winbindd_child *child)
}
ZERO_STRUCT(state);
- state.pid = getpid();
+ state.pid = sys_getpid();
+
+ /* Stop zombies */
+ CatchChild();
/* Ensure we don't process messages whilst we're
changing the disposition for the child. */
@@ -732,25 +848,47 @@ static BOOL fork_domain_child(struct winbindd_child *child)
/* The child is ok with online/offline messages now. */
message_unblock();
- child->mem_ctx = talloc_init("child_mem_ctx");
- if (child->mem_ctx == NULL) {
- return False;
+ /* Handle online/offline messages. */
+ message_register(MSG_WINBIND_OFFLINE, child_msg_offline, NULL);
+ message_register(MSG_WINBIND_ONLINE, child_msg_online, NULL);
+ message_register(MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus,
+ NULL);
+
+ if ( child->domain ) {
+ child->domain->startup = True;
+ child->domain->startup_time = time(NULL);
}
- if (child->domain != NULL && lp_winbind_offline_logon()) {
- /* We might be in the idmap child...*/
- child->lockout_policy_event = add_timed_event(
- child->mem_ctx, timeval_zero(),
+ /* Ensure we have no pending check_online events other
+ than one for this domain. */
+
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if (domain != child->domain) {
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+ }
+ }
+
+ /* Ensure we're not handling an event inherited from
+ our parent. */
+
+ cancel_named_event(winbind_event_context(),
+ "krb5_ticket_refresh_handler");
+
+ /* We might be in the idmap child...*/
+ if (child->domain && !(child->domain->internal) &&
+ lp_winbind_offline_logon()) {
+
+ set_domain_online_request(child->domain);
+
+ child->lockout_policy_event = event_add_timed(
+ winbind_event_context(), NULL, timeval_zero(),
"account_lockout_policy_handler",
account_lockout_policy_handler,
child);
}
- /* Handle online/offline messages. */
- message_register(MSG_WINBIND_OFFLINE,child_msg_offline);
- message_register(MSG_WINBIND_ONLINE,child_msg_online);
- message_register(MSG_WINBIND_ONLINESTATUS,child_msg_onlinestatus);
-
while (1) {
int ret;
@@ -763,11 +901,19 @@ static BOOL fork_domain_child(struct winbindd_child *child)
lp_TALLOC_FREE();
main_loop_TALLOC_FREE();
- run_events();
+ run_events(winbind_event_context(), 0, NULL, NULL);
GetTimeOfDay(&now);
- tp = get_timed_events_timeout(&t);
+ if (child->domain && child->domain->startup &&
+ (now.tv_sec > child->domain->startup_time + 30)) {
+ /* No longer in "startup" mode. */
+ DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
+ child->domain->name ));
+ child->domain->startup = False;
+ }
+
+ tp = get_timed_events_timeout(winbind_event_context(), &t);
if (tp) {
DEBUG(11,("select will use timeout of %u.%u seconds\n",
(unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
@@ -822,7 +968,8 @@ static BOOL fork_domain_child(struct winbindd_child *child)
* structure needs to be fetched via the
* winbindd_cache. Hmm. That needs fixing... */
- if (write_data(state.sock, (void *)&state.response.result,
+ if (write_data(state.sock,
+ (const char *)&state.response.result,
sizeof(state.response.result)) !=
sizeof(state.response.result)) {
DEBUG(0, ("Could not write result\n"));
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index b6dffd1098e..7edb755f1c0 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -31,9 +31,150 @@ extern BOOL opt_nocache;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-/***************************************************************
- Empty static struct for negative caching.
-****************************************************************/
+static void add_member(const char *domain, const char *user,
+ char **pp_members, size_t *p_num_members)
+{
+ fstring name;
+
+ fill_domain_username(name, domain, user, True);
+ safe_strcat(name, ",", sizeof(name)-1);
+ string_append(pp_members, name);
+ *p_num_members += 1;
+}
+
+/**********************************************************************
+ Add member users resulting from sid. Expand if it is a domain group.
+**********************************************************************/
+
+static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_num_members)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+ struct winbindd_domain *domain;
+ size_t i;
+
+ char *domain_name = NULL;
+ char *name = NULL;
+ enum lsa_SidType type;
+
+ uint32 num_names;
+ DOM_SID *sid_mem;
+ char **names;
+ uint32 *types;
+
+ NTSTATUS result;
+
+ TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
+
+ if (mem_ctx == NULL) {
+ DEBUG(1, ("talloc_init failed\n"));
+ return;
+ }
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ domain = find_lookup_domain_from_sid(sid);
+
+ if (domain == NULL) {
+ DEBUG(3, ("Could not find domain for sid %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
+
+ result = domain->methods->sid_to_name(domain, mem_ctx, sid,
+ &domain_name, &name, &type);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(3, ("sid_to_name failed for sid %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
+
+ DEBUG(10, ("Found name %s, type %d\n", name, type));
+
+ if (type == SID_NAME_USER) {
+ add_member(domain_name, name, pp_members, p_num_members);
+ goto done;
+ }
+
+ if (type != SID_NAME_DOM_GRP) {
+ DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
+ name));
+ goto done;
+ }
+
+ /* Expand the domain group, this must be done via the target domain */
+
+ domain = find_domain_from_sid(sid);
+
+ if (domain == NULL) {
+ DEBUG(3, ("Could not find domain from SID %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
+
+ result = domain->methods->lookup_groupmem(domain, mem_ctx,
+ sid, &num_names,
+ &sid_mem, &names,
+ &types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("Could not lookup group members for %s: %s\n",
+ name, nt_errstr(result)));
+ goto done;
+ }
+
+ for (i=0; i<num_names; i++) {
+ DEBUG(10, ("Adding group member SID %s\n",
+ sid_string_static(&sid_mem[i])));
+
+ if (types[i] != SID_NAME_USER) {
+ DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
+ "Ignoring.\n", names[i], name));
+ continue;
+ }
+
+ add_member(domain->name, names[i], pp_members, p_num_members);
+ }
+
+ done:
+ talloc_destroy(mem_ctx);
+ return;
+}
+
+static BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
+ DOM_SID *group_sid,
+ size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len)
+{
+ DOM_SID *members;
+ size_t i, num_members;
+
+ *num_gr_mem = 0;
+ *gr_mem = NULL;
+ *gr_mem_len = 0;
+
+ if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
+ &num_members)))
+ return True;
+
+ for (i=0; i<num_members; i++) {
+ add_expanded_sid(&members[i], gr_mem, num_gr_mem);
+ }
+
+ TALLOC_FREE(members);
+
+ if (*gr_mem != NULL) {
+ size_t len;
+
+ /* We have at least one member, strip off the last "," */
+ len = strlen(*gr_mem);
+ (*gr_mem)[len-1] = '\0';
+ *gr_mem_len = len;
+ }
+
+ return True;
+}
/* Fill a grent structure from various other information */
@@ -57,18 +198,20 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
/* Fill in the group membership field of a NT group given by group_sid */
static BOOL fill_grent_mem(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state,
DOM_SID *group_sid,
- enum SID_NAME_USE group_name_type,
+ enum lsa_SidType group_name_type,
size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len)
{
DOM_SID *sid_mem = NULL;
uint32 num_names = 0;
uint32 *name_types = NULL;
- unsigned int buf_len, buf_ndx, i;
- char **names = NULL, *buf;
+ unsigned int buf_len = 0, buf_ndx = 0, i;
+ char **names = NULL, *buf = NULL;
BOOL result = False;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
+ uint32 group_rid;
fstring sid_string;
if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name)))
@@ -78,6 +221,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid)));
+ /* Initialize with no members */
*num_gr_mem = 0;
/* HACK ALERT!! This whole routine does not cope with group members
@@ -98,13 +242,125 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
goto done;
}
+ /* OPTIMIZATION / HACK. */
+ /* If "enum users" is set to false, and the group being looked
+ up is the Domain Users SID: S-1-5-domain-513, then for the
+ list of members check if the querying user is in that group,
+ and if so only return that user as the gr_mem array.
+ We can change this to a different parameter than "enum users"
+ if neccessaey, or parameterize the group list we do this for. */
+
+ sid_peek_rid( group_sid, &group_rid );
+ if (!lp_winbind_enum_users() && group_rid == DOMAIN_GROUP_RID_USERS) {
+ DOM_SID querying_user_sid;
+ DOM_SID *pquerying_user_sid = NULL;
+ uint32 num_groups = 0;
+ DOM_SID *user_sids = NULL;
+ BOOL u_in_group = False;
+
+ DEBUG(10,("fill_grent_mem: optimized lookup for sid %s domain %s\n",
+ sid_to_string(sid_string, group_sid), domain->name ));
+
+ if (state) {
+ uid_t ret_uid = (uid_t)-1;
+ if (sys_getpeereid(state->sock, &ret_uid)==0) {
+ /* We know who's asking - look up their SID if
+ it's one we've mapped before. */
+ status = idmap_uid_to_sid(&querying_user_sid, ret_uid);
+ if (NT_STATUS_IS_OK(status)) {
+ pquerying_user_sid = &querying_user_sid;
+ DEBUG(10,("fill_grent_mem: querying uid %u -> %s\n",
+ (unsigned int)ret_uid,
+ sid_to_string(sid_string, pquerying_user_sid) ));
+ }
+ }
+ }
+
+ /* Only look up if it was a winbindd user in this domain. */
+ if (pquerying_user_sid &&
+ (sid_compare_domain(pquerying_user_sid, &domain->sid) == 0)) {
+
+ DEBUG(10,("fill_grent_mem: querying user = %s\n",
+ sid_to_string(sid_string, pquerying_user_sid) ));
+
+ status = domain->methods->lookup_usergroups(domain,
+ mem_ctx,
+ pquerying_user_sid,
+ &num_groups,
+ &user_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("fill_grent_mem: lookup_usergroups failed "
+ "for sid %s in domain %s (error: %s)\n",
+ sid_to_string(sid_string, pquerying_user_sid),
+ domain->name,
+ nt_errstr(status)));
+ goto done;
+ }
+
+ for (i = 0; i < num_groups; i++) {
+ if (sid_equal(group_sid, &user_sids[i])) {
+ /* User is in Domain Users, add their name
+ as the only group member. */
+ u_in_group = True;
+ break;
+ }
+ }
+ }
+
+ if (u_in_group) {
+ size_t len = 0;
+ char *domainname = NULL;
+ char *username = NULL;
+ fstring name;
+ enum lsa_SidType type;
+
+ DEBUG(10,("fill_grent_mem: sid %s in 'Domain Users' in domain %s\n",
+ sid_to_string(sid_string, pquerying_user_sid), domain->name ));
+
+ status = domain->methods->sid_to_name(domain, mem_ctx,
+ pquerying_user_sid,
+ &domainname,
+ &username,
+ &type);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("could not lookup username for user "
+ "sid %s in domain %s (error: %s)\n",
+ sid_to_string(sid_string, pquerying_user_sid),
+ domain->name,
+ nt_errstr(status)));
+ goto done;
+ }
+ fill_domain_username(name, domain->name, username, True);
+ len = strlen(name);
+ buf_len = len + 1;
+ if (!(buf = (char *)SMB_MALLOC(buf_len))) {
+ DEBUG(1, ("out of memory\n"));
+ goto done;
+ }
+ memcpy(buf, name, buf_len);
+
+ DEBUG(10,("fill_grent_mem: user %s in 'Domain Users' in domain %s\n",
+ name, domain->name ));
+
+ /* user is the only member */
+ *num_gr_mem = 1;
+ }
+
+ *gr_mem = buf;
+ *gr_mem_len = buf_len;
+
+ DEBUG(10, ("num_mem = %u, len = %u, mem = %s\n", (unsigned int)*num_gr_mem,
+ (unsigned int)buf_len, *num_gr_mem ? buf : "NULL"));
+ result = True;
+ goto done;
+ }
+
/* Lookup group members */
status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names,
&sid_mem, &names, &name_types);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n",
+ DEBUG(1, ("could not lookup membership for group sid %s in domain %s (error: %s)\n",
sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status)));
-
goto done;
}
@@ -119,9 +375,6 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
/* Add members to list */
- buf = NULL;
- buf_len = buf_ndx = 0;
-
again:
for (i = 0; i < num_names; i++) {
@@ -157,7 +410,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
(*num_gr_mem)++;
DEBUG(10, ("buf_len + %d = %d\n", len + 1, buf_len));
} else {
- DEBUG(10, ("appending %s at ndx %d\n", name, len));
+ DEBUG(10, ("appending %s at ndx %d\n", name, buf_ndx));
safe_strcpy(&buf[buf_ndx], name, len);
buf_ndx += len;
buf[buf_ndx] = ',';
@@ -168,7 +421,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
/* Allocate buffer */
if (!buf && buf_len != 0) {
- if (!(buf = SMB_MALLOC(buf_len))) {
+ if (!(buf = (char *)SMB_MALLOC(buf_len))) {
DEBUG(1, ("out of memory\n"));
result = False;
goto done;
@@ -204,7 +457,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
DOM_SID group_sid, tmp_sid;
uint32 grp_rid;
struct winbindd_domain *domain;
- enum SID_NAME_USE name_type;
+ enum lsa_SidType name_type;
fstring name_domain, name_group;
char *tmp, *gr_mem;
size_t gr_mem_len;
@@ -252,6 +505,8 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
}
/* Get rid and name type from name */
+
+ ws_name_replace( name_group, '_' );
if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, domain->name,
name_group, &group_sid, &name_type)) {
@@ -288,7 +543,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
/* Try to get the GID */
- status = idmap_sid_to_gid(&group_sid, &gid, 0);
+ status = idmap_sid_to_gid(&group_sid, &gid);
if (NT_STATUS_IS_OK(status)) {
goto got_gid;
@@ -311,7 +566,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
if (!fill_grent(&state->response.data.gr, name_domain,
name_group, gid) ||
- !fill_grent_mem(domain, &group_sid, name_type,
+ !fill_grent_mem(domain, state, &group_sid, name_type,
&num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
@@ -332,19 +587,21 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid)
{
struct winbindd_domain *domain;
- enum SID_NAME_USE name_type;
- fstring dom_name;
- fstring group_name;
+ enum lsa_SidType name_type;
+ char *dom_name;
+ char *group_name;
size_t gr_mem_len;
size_t num_gr_mem;
char *gr_mem;
/* Get name from sid */
- if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, dom_name,
- group_name, &name_type)) {
+ if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, &dom_name,
+ &group_name, &name_type)) {
DEBUG(1, ("could not lookup sid\n"));
request_error(state);
+ TALLOC_FREE(group_name);
+ TALLOC_FREE(dom_name);
return;
}
@@ -355,6 +612,8 @@ static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid
if (!domain) {
DEBUG(1,("Can't find domain from sid\n"));
request_error(state);
+ TALLOC_FREE(group_name);
+ TALLOC_FREE(dom_name);
return;
}
@@ -365,15 +624,19 @@ static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
group_name, name_type));
request_error(state);
+ TALLOC_FREE(group_name);
+ TALLOC_FREE(dom_name);
return;
}
if (!fill_grent(&state->response.data.gr, dom_name, group_name,
state->request.data.gid) ||
- !fill_grent_mem(domain, &group_sid, name_type,
+ !fill_grent_mem(domain, state, &group_sid, name_type,
&num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
+ TALLOC_FREE(group_name);
+ TALLOC_FREE(dom_name);
return;
}
@@ -386,13 +649,16 @@ static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid
state->response.length += gr_mem_len;
state->response.extra_data.data = gr_mem;
+ TALLOC_FREE(group_name);
+ TALLOC_FREE(dom_name);
+
request_ok(state);
}
static void getgrgid_recv(void *private_data, BOOL success, const char *sid)
{
struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state);
- enum SID_NAME_USE name_type;
+ enum lsa_SidType name_type;
DOM_SID group_sid;
if (success) {
@@ -423,32 +689,10 @@ static void getgrgid_recv(void *private_data, BOOL success, const char *sid)
/* Return a group structure from a gid number */
void winbindd_getgrgid(struct winbindd_cli_state *state)
{
- DOM_SID group_sid;
- NTSTATUS status;
-
DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.gid));
- /* Bug out if the gid isn't in the winbind range */
-
- if ((state->request.data.gid < server_state.gid_low) ||
- (state->request.data.gid > server_state.gid_high)) {
- request_error(state);
- return;
- }
-
- /* Get sid from gid */
-
- status = idmap_gid_to_sid(&group_sid, state->request.data.gid, ID_EMPTY);
- if (NT_STATUS_IS_OK(status)) {
- /* This is a remote one */
- getgrgid_got_sid(state, group_sid);
- return;
- }
-
- DEBUG(10,("winbindd_getgrgid: gid %lu not found in cache, try with the async interface\n",
- (unsigned long)state->request.data.gid));
-
+ /* always use the async interface */
winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, getgrgid_recv, state);
}
@@ -730,7 +974,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
break;
}
- name_list = ent->sam_entries;
+ name_list = (struct acct_info *)ent->sam_entries;
if (!(domain =
find_domain_from_name(ent->domain_name))) {
@@ -744,10 +988,9 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
sid_copy(&group_sid, &domain->sid);
sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
- if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid,
- &group_gid, 0))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid))) {
union unid_t id;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
DEBUG(10, ("SID %s not in idmap\n",
sid_string_static(&group_sid)));
@@ -802,6 +1045,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid);
result = fill_grent_mem(
domain,
+ NULL,
&member_sid,
SID_NAME_DOM_GRP,
&num_gr_mem,
@@ -813,7 +1057,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
if (result) {
/* Append to group membership list */
- gr_mem_list = SMB_REALLOC( gr_mem_list, gr_mem_list_len + gr_mem_len);
+ gr_mem_list = (char *)SMB_REALLOC(
+ gr_mem_list, gr_mem_list_len + gr_mem_len);
if (!gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) {
DEBUG(0, ("out of memory\n"));
@@ -941,7 +1186,8 @@ void winbindd_list_groups(struct winbindd_cli_state *state)
/* Allocate some memory for extra data. Note that we limit
account names to sizeof(fstring) = 128 characters. */
- extra_data = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
+ extra_data = (char *)SMB_REALLOC(
+ extra_data, sizeof(fstring) * total_entries);
if (!extra_data) {
DEBUG(0,("failed to enlarge buffer!\n"));
@@ -1000,7 +1246,7 @@ struct getgroups_state {
};
static void getgroups_usersid_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type);
+ const DOM_SID *sid, enum lsa_SidType type);
static void getgroups_tokensids_recv(void *private_data, BOOL success,
DOM_SID *token_sids, size_t num_token_sids);
static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid);
@@ -1056,7 +1302,7 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
}
if ( s->domain->primary && lp_winbind_trusted_domains_only()) {
- DEBUG(7,("winbindd_getpwnam: My domain -- rejecting "
+ DEBUG(7,("winbindd_getgroups: My domain -- rejecting "
"getgroups() for %s\\%s.\n", s->domname,
s->username));
request_error(state);
@@ -1070,9 +1316,10 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
}
static void getgroups_usersid_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type)
+ const DOM_SID *sid, enum lsa_SidType type)
{
- struct getgroups_state *s = private_data;
+ struct getgroups_state *s =
+ (struct getgroups_state *)private_data;
if ((!success) ||
((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))) {
@@ -1089,7 +1336,8 @@ static void getgroups_usersid_recv(void *private_data, BOOL success,
static void getgroups_tokensids_recv(void *private_data, BOOL success,
DOM_SID *token_sids, size_t num_token_sids)
{
- struct getgroups_state *s = private_data;
+ struct getgroups_state *s =
+ (struct getgroups_state *)private_data;
/* We need at least the user sid and the primary group in the token,
* otherwise it's an error */
@@ -1111,12 +1359,16 @@ static void getgroups_tokensids_recv(void *private_data, BOOL success,
static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
{
- struct getgroups_state *s = private_data;
+ struct getgroups_state *s =
+ (struct getgroups_state *)private_data;
- if (success)
- add_gid_to_array_unique(NULL, gid,
+ if (success) {
+ if (!add_gid_to_array_unique(s->state->mem_ctx, gid,
&s->token_gids,
- &s->num_token_gids);
+ &s->num_token_gids)) {
+ return;
+ }
+ }
if (s->i < s->num_token_sids) {
const DOM_SID *sid = &s->token_sids[s->i];
@@ -1133,7 +1385,8 @@ static void getgroups_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
}
s->state->response.data.num_entries = s->num_token_gids;
- s->state->response.extra_data.data = s->token_gids;
+ /* s->token_gids are talloced */
+ s->state->response.extra_data.data = smb_xmemdup(s->token_gids, s->num_token_gids * sizeof(gid_t));
s->state->response.length += s->num_token_gids * sizeof(gid_t);
request_ok(s->state);
}
@@ -1181,7 +1434,8 @@ void winbindd_getusersids(struct winbindd_cli_state *state)
static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids,
size_t num_sids)
{
- struct winbindd_cli_state *state = private_data;
+ struct winbindd_cli_state *state =
+ (struct winbindd_cli_state *)private_data;
char *ret = NULL;
unsigned ofs, ret_size = 0;
size_t i;
@@ -1198,7 +1452,7 @@ static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids,
}
/* build the reply */
- ret = SMB_MALLOC(ret_size);
+ ret = (char *)SMB_MALLOC(ret_size);
if (!ret) {
DEBUG(0, ("malloc failed\n"));
request_error(state);
@@ -1276,12 +1530,15 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
return WINBINDD_OK;
}
- if (!print_sidlist(NULL, groups, num_groups, &sidstring, &len)) {
- DEBUG(0, ("malloc failed\n"));
+ if (!print_sidlist(state->mem_ctx, groups, num_groups, &sidstring, &len)) {
+ DEBUG(0, ("talloc failed\n"));
return WINBINDD_ERROR;
}
- state->response.extra_data.data = sidstring;
+ state->response.extra_data.data = SMB_STRDUP(sidstring);
+ if (!state->response.extra_data.data) {
+ return WINBINDD_ERROR;
+ }
state->response.length += len+1;
state->response.data.num_entries = num_groups;
diff --git a/source/nsswitch/winbindd_misc.c b/source/nsswitch/winbindd_misc.c
index 6b44eb9783b..f5363cad1a2 100644
--- a/source/nsswitch/winbindd_misc.c
+++ b/source/nsswitch/winbindd_misc.c
@@ -124,6 +124,12 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
&num_domains, &names,
&alt_names, &sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
+ nt_errstr(result) ));
+ return WINBINDD_ERROR;
+ }
+
extra_data = talloc_strdup(state->mem_ctx, "");
if (num_domains > 0)
@@ -304,7 +310,8 @@ void winbindd_show_sequence(struct winbindd_cli_state *state)
static void sequence_recv(void *private_data, BOOL success)
{
- struct sequence_state *state = private_data;
+ struct sequence_state *state =
+ (struct sequence_state *)private_data;
uint32 seq = DOM_SEQUENCE_NONE;
if ((success) && (state->response->result == WINBINDD_OK))
@@ -425,7 +432,8 @@ void winbindd_domain_info(struct winbindd_cli_state *state)
static void domain_info_init_recv(void *private_data, BOOL success)
{
- struct domain_info_state *istate = private_data;
+ struct domain_info_state *istate =
+ (struct domain_info_state *)private_data;
struct winbindd_cli_state *state = istate->cli_state;
struct winbindd_domain *domain = istate->domain;
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index 9b69eb091d2..b6c262e4667 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -35,7 +35,7 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 14
+#define WINBIND_INTERFACE_VERSION 18
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
On a 64bit Linux box, we have to support a constant structure size
@@ -77,6 +77,7 @@ enum winbindd_cmd {
WINBINDD_PAM_AUTH_CRAP,
WINBINDD_PAM_CHAUTHTOK,
WINBINDD_PAM_LOGOFF,
+ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
/* List various things */
@@ -88,19 +89,25 @@ enum winbindd_cmd {
WINBINDD_LOOKUPSID,
WINBINDD_LOOKUPNAME,
+ WINBINDD_LOOKUPRIDS,
/* Lookup functions */
WINBINDD_SID_TO_UID,
WINBINDD_SID_TO_GID,
+ WINBINDD_SIDS_TO_XIDS,
WINBINDD_UID_TO_SID,
WINBINDD_GID_TO_SID,
WINBINDD_ALLOCATE_UID,
WINBINDD_ALLOCATE_GID,
+ WINBINDD_SET_MAPPING,
+ WINBINDD_SET_HWM,
/* Miscellaneous other stuff */
+ WINBINDD_DUMP_MAPS,
+
WINBINDD_CHECK_MACHACC, /* Check machine account pw works */
WINBINDD_PING, /* Just tell me winbind is running */
WINBINDD_INFO, /* Various bit of info. Currently just tidbits */
@@ -138,9 +145,12 @@ enum winbindd_cmd {
* between parent and children */
WINBINDD_DUAL_SID2UID,
WINBINDD_DUAL_SID2GID,
+ WINBINDD_DUAL_SIDS2XIDS,
WINBINDD_DUAL_UID2SID,
WINBINDD_DUAL_GID2SID,
- WINBINDD_DUAL_IDMAPSET,
+ WINBINDD_DUAL_SET_MAPPING,
+ WINBINDD_DUAL_SET_HWM,
+ WINBINDD_DUAL_DUMP_MAPS,
/* Wrapper around possibly blocking unix nss calls */
WINBINDD_DUAL_UID2NAME,
@@ -151,6 +161,10 @@ enum winbindd_cmd {
WINBINDD_DUAL_USERINFO,
WINBINDD_DUAL_GETSIDALIASES,
+ /* Complete the challenge phase of the NTLM authentication
+ protocol using cached password. */
+ WINBINDD_CCACHE_NTLMAUTH,
+
WINBINDD_NUM_CMDS
};
@@ -225,7 +239,7 @@ struct winbindd_request {
character is. */
fstring user;
fstring pass;
- fstring require_membership_of_sid;
+ pstring require_membership_of_sid;
fstring krb5_cc_type;
uid_t uid;
} auth; /* pam_winbind auth module */
@@ -248,6 +262,18 @@ struct winbindd_request {
} chauthtok; /* pam_winbind passwd module */
struct {
fstring user;
+ fstring domain;
+ unsigned char new_nt_pswd[516];
+ uint16 new_nt_pswd_len;
+ unsigned char old_nt_hash_enc[16];
+ uint16 old_nt_hash_enc_len;
+ unsigned char new_lm_pswd[516];
+ uint16 new_lm_pswd_len;
+ unsigned char old_lm_hash_enc[16];
+ uint16 old_lm_hash_enc_len;
+ } chng_pswd_auth_crap;/* pam_winbind passwd module */
+ struct {
+ fstring user;
fstring krb5ccname;
uid_t uid;
} logoff; /* pam_winbind session module */
@@ -268,18 +294,29 @@ struct winbindd_request {
struct {
fstring sid;
fstring name;
- BOOL alloc;
} dual_sid2id;
struct {
- int type;
- uid_t uid;
- gid_t gid;
fstring sid;
+ uint32 type;
+ uint32 id;
} dual_idmapset;
BOOL list_all_domains;
+ struct {
+ uid_t uid;
+ fstring user;
+ /* the effective uid of the client, must be the uid for 'user'.
+ This is checked by the main daemon, trusted by children. */
+ /* if the blobs are length zero, then this doesn't
+ produce an actual challenge response. It merely
+ succeeds if there are cached credentials available
+ that could be used. */
+ uint32 initial_blob_len; /* blobs in extra_data */
+ uint32 challenge_blob_len;
+ } ccache_ntlm_auth;
+
/* padding -- needed to fix alignment between 32bit and 64bit libs.
- The size if the sizeof the union without the padding aligned on
+ The size is the sizeof the union without the padding aligned on
an 8 byte boundary. --jerry */
char padding[1560];
@@ -410,8 +447,12 @@ struct winbindd_response {
fstring full_name;
fstring homedir;
fstring shell;
+ uint32 primary_gid;
uint32 group_rid;
} user_info;
+ struct {
+ uint32 auth_blob_len; /* blob in extra_data */
+ } ccache_ntlm_auth;
} data;
/* Variable length return data */
@@ -422,20 +463,31 @@ struct winbindd_response {
} extra_data;
};
+struct WINBINDD_MEMORY_CREDS {
+ struct WINBINDD_MEMORY_CREDS *next, *prev;
+ const char *username; /* lookup key. */
+ uid_t uid;
+ int ref_count;
+ size_t len;
+ unsigned char *nt_hash; /* Base pointer for the following 2 */
+ unsigned char *lm_hash;
+ char *pass;
+};
+
struct WINBINDD_CCACHE_ENTRY {
+ struct WINBINDD_CCACHE_ENTRY *next, *prev;
const char *principal_name;
const char *ccname;
const char *service;
const char *username;
- const char *sid_string;
- char *pass;
+ const char *realm;
+ struct WINBINDD_MEMORY_CREDS *cred_ptr;
+ int ref_count;
uid_t uid;
time_t create_time;
time_t renew_until;
- BOOL refresh_tgt;
time_t refresh_time;
struct timed_event *event;
- struct WINBINDD_CCACHE_ENTRY *next, *prev;
};
#endif
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index bab2b03f66c..2e679c37dcf 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -35,17 +35,17 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
fstring str_sid;
state->response.data.auth.info3.logon_time =
- nt_time_to_unix(&(info3->logon_time));
+ nt_time_to_unix(info3->logon_time);
state->response.data.auth.info3.logoff_time =
- nt_time_to_unix(&(info3->logoff_time));
+ nt_time_to_unix(info3->logoff_time);
state->response.data.auth.info3.kickoff_time =
- nt_time_to_unix(&(info3->kickoff_time));
+ nt_time_to_unix(info3->kickoff_time);
state->response.data.auth.info3.pass_last_set_time =
- nt_time_to_unix(&(info3->pass_last_set_time));
+ nt_time_to_unix(info3->pass_last_set_time);
state->response.data.auth.info3.pass_can_change_time =
- nt_time_to_unix(&(info3->pass_can_change_time));
+ nt_time_to_unix(info3->pass_can_change_time);
state->response.data.auth.info3.pass_must_change_time =
- nt_time_to_unix(&(info3->pass_must_change_time));
+ nt_time_to_unix(info3->pass_must_change_time);
state->response.data.auth.info3.logon_count = info3->logon_count;
state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count;
@@ -104,7 +104,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
memset( state->response.extra_data.data, '\0', size );
- prs_copy_all_data_out(state->response.extra_data.data, &ps);
+ prs_copy_all_data_out((char *)state->response.extra_data.data, &ps);
state->response.length += size;
prs_mem_free(&ps);
return NT_STATUS_OK;
@@ -113,11 +113,27 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
NET_USER_INFO_3 *info3,
const char *group_sid)
+/**
+ * Check whether a user belongs to a group or list of groups.
+ *
+ * @param mem_ctx talloc memory context.
+ * @param info3 user information, including group membership info.
+ * @param group_sid One or more groups , separated by commas.
+ *
+ * @return NT_STATUS_OK on success,
+ * NT_STATUS_LOGON_FAILURE if the user does not belong,
+ * or other NT_STATUS_IS_ERR(status) for other kinds of failure.
+ */
{
- DOM_SID require_membership_of_sid;
+ DOM_SID *require_membership_of_sid;
+ size_t num_require_membership_of_sid;
DOM_SID *all_sids;
size_t num_all_sids = (2 + info3->num_groups2 + info3->num_other_sids);
- size_t i, j = 0;
+ size_t i, j = 0, k;
+ size_t group_sid_length;
+ const char *search_location;
+ char *single_group_sid;
+ const char *comma;
/* Parse the 'required group' SID */
@@ -125,10 +141,48 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
/* NO sid supplied, all users may access */
return NT_STATUS_OK;
}
-
- if (!string_to_sid(&require_membership_of_sid, group_sid)) {
+
+ num_require_membership_of_sid = 1;
+ group_sid_length = strlen(group_sid);
+ for (i = 0; i < group_sid_length; i++) {
+ if (',' == group_sid[i]) {
+ num_require_membership_of_sid++;
+ }
+ }
+
+ require_membership_of_sid = TALLOC_ARRAY(mem_ctx, DOM_SID, num_require_membership_of_sid);
+ if (!require_membership_of_sid)
+ return NT_STATUS_NO_MEMORY;
+
+ i = 0;
+ search_location = group_sid;
+
+ if (num_require_membership_of_sid > 1) {
+
+ /* Allocate the maximum possible size */
+ single_group_sid = TALLOC(mem_ctx, group_sid_length);
+ if (!single_group_sid)
+ return NT_STATUS_NO_MEMORY;
+
+ while ( (comma = strstr(search_location, ",")) != NULL ) {
+
+ strncpy(single_group_sid, search_location, comma - search_location);
+ single_group_sid[comma - search_location] = 0;
+
+ if (!string_to_sid(&require_membership_of_sid[i++], single_group_sid)) {
+ DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!",
+ single_group_sid));
+
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ search_location = comma + 1;
+ }
+ }
+
+ if (!string_to_sid(&require_membership_of_sid[i++], search_location)) {
DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!",
- group_sid));
+ search_location));
return NT_STATUS_INVALID_PARAMETER;
}
@@ -188,10 +242,12 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
fstring sid1, sid2;
DEBUG(10, ("User has SID: %s\n",
sid_to_string(sid1, &all_sids[i])));
- if (sid_equal(&require_membership_of_sid, &all_sids[i])) {
- DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n",
- sid_to_string(sid1, &require_membership_of_sid), sid_to_string(sid2, &all_sids[i])));
- return NT_STATUS_OK;
+ for (k = 0; k < num_require_membership_of_sid; k++) {
+ if (sid_equal(&require_membership_of_sid[k], &all_sids[i])) {
+ DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n",
+ sid_to_string(sid1, &require_membership_of_sid[k]), sid_to_string(sid2, &all_sids[i])));
+ return NT_STATUS_OK;
+ }
}
}
@@ -200,8 +256,8 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
return NT_STATUS_LOGON_FAILURE;
}
-static struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state,
- const char *domain_name)
+struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state,
+ const char *domain_name)
{
struct winbindd_domain *domain;
@@ -321,6 +377,8 @@ static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+#ifdef HAVE_KRB5
+
static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx,
const char *type,
uid_t uid,
@@ -368,19 +426,6 @@ static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx,
return gen_cc;
}
-static uid_t get_uid_from_state(struct winbindd_cli_state *state)
-{
- uid_t uid = -1;
-
- uid = state->request.data.auth.uid;
-
- if (uid < 0) {
- DEBUG(1,("invalid uid: '%d'\n", uid));
- return -1;
- }
- return uid;
-}
-
static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc)
{
const char *type = state->request.data.auth.krb5_cc_type;
@@ -401,10 +446,26 @@ static void setup_return_cc_name(struct winbindd_cli_state *state, const char *c
fstrcpy(state->response.data.auth.krb5ccname, cc);
}
+#endif
+
+static uid_t get_uid_from_state(struct winbindd_cli_state *state)
+{
+ uid_t uid = -1;
+
+ uid = state->request.data.auth.uid;
+
+ if (uid < 0) {
+ DEBUG(1,("invalid uid: '%d'\n", uid));
+ return -1;
+ }
+ return uid;
+}
+
/**********************************************************************
Authenticate a user with a clear text password using Kerberos and fill up
ccache if required
**********************************************************************/
+
static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
struct winbindd_cli_state *state,
NET_USER_INFO_3 **info3)
@@ -537,7 +598,8 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
&tkt,
&session_key_krb5,
0,
- cc);
+ cc,
+ NULL);
if (krb5_ret) {
DEBUG(1,("winbindd_raw_kerberos_login: failed to get ticket for %s: %s\n",
local_service, error_message(krb5_ret)));
@@ -598,18 +660,28 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
cc,
service,
state->request.data.auth.user,
- NULL,
- state->request.data.auth.pass,
+ realm,
uid,
time(NULL),
ticket_lifetime,
renewal_until,
- lp_winbind_refresh_tickets());
+ False);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
nt_errstr(result)));
}
+ } else {
+
+ /* need to delete the memory cred cache, it is not used anymore */
+
+ krb5_ret = ads_kdestroy(cc);
+ if (krb5_ret) {
+ DEBUG(3,("winbindd_raw_kerberos_login: "
+ "could not destroy krb5 credential cache: "
+ "%s\n", error_message(krb5_ret)));
+ }
+
}
result = NT_STATUS_OK;
@@ -630,9 +702,10 @@ failed:
"%s\n", error_message(krb5_ret)));
}
- if (!NT_STATUS_IS_OK(remove_ccache_by_ccname(cc))) {
+ if (!NT_STATUS_IS_OK(remove_ccache(state->request.data.auth.user))) {
DEBUG(3,("winbindd_raw_kerberos_login: "
- "could not remove ccache\n"));
+ "could not remove ccache for user %s\n",
+ state->request.data.auth.user));
}
done:
@@ -671,7 +744,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
/* Parse domain and username */
- if (!parse_domain_user(state->request.data.auth.user,
+ if (!canonicalize_username(state->request.data.auth.user,
name_domain, name_user)) {
set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
DEBUG(5, ("Plain text authentication for %s returned %s "
@@ -707,11 +780,13 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
uint16 max_allowed_bad_attempts;
fstring name_domain, name_user;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
uchar new_nt_pass[NT_HASH_LEN];
const uint8 *cached_nt_pass;
+ const uint8 *cached_salt;
NET_USER_INFO_3 *my_info3;
time_t kickoff_time, must_change_time;
+ BOOL password_good = False;
*info3 = NULL;
@@ -742,7 +817,8 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
state->mem_ctx,
&sid,
&my_info3,
- &cached_nt_pass);
+ &cached_nt_pass,
+ &cached_salt);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
return result;
@@ -755,9 +831,26 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
#if DEBUG_PASSWORD
dump_data(100, (const char *)new_nt_pass, NT_HASH_LEN);
dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
+ if (cached_salt) {
+ dump_data(100, (const char *)cached_salt, NT_HASH_LEN);
+ }
#endif
- if (!memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN)) {
+ if (cached_salt) {
+ /* In this case we didn't store the nt_hash itself,
+ but the MD5 combination of salt + nt_hash. */
+ uchar salted_hash[NT_HASH_LEN];
+ E_md5hash(cached_salt, new_nt_pass, salted_hash);
+
+ password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ?
+ True : False;
+ } else {
+ /* Old cached cred - direct store of nt_hash (bad bad bad !). */
+ password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ?
+ True : False;
+ }
+
+ if (password_good) {
/* User *DOES* know the password, update logon_time and reset
* bad_pw_count */
@@ -784,25 +877,88 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
}
- /* The info3 acct_flags in NT4's samlogon reply don't have
- * ACB_NORMAL set. */
-#if 0
if (!(my_info3->acct_flags & ACB_NORMAL)) {
- DEBUG(10,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n",
+ DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n",
my_info3->acct_flags));
return NT_STATUS_LOGON_FAILURE;
}
-#endif
- kickoff_time = nt_time_to_unix(&my_info3->kickoff_time);
+
+ kickoff_time = nt_time_to_unix(my_info3->kickoff_time);
if (kickoff_time != 0 && time(NULL) > kickoff_time) {
return NT_STATUS_ACCOUNT_EXPIRED;
}
- must_change_time = nt_time_to_unix(&my_info3->pass_must_change_time);
+ must_change_time = nt_time_to_unix(my_info3->pass_must_change_time);
if (must_change_time != 0 && must_change_time < time(NULL)) {
- return NT_STATUS_PASSWORD_EXPIRED;
+ /* we allow grace logons when the password has expired */
+ my_info3->user_flgs |= LOGON_GRACE_LOGON;
+ /* return NT_STATUS_PASSWORD_EXPIRED; */
+ goto success;
}
+#ifdef HAVE_KRB5
+ /* FIXME: what else points out that the remote domain is AD ? */
+ if (!strequal(domain->name, domain->alt_name) &&
+ (state->request.flags & WBFLAG_PAM_KRB5)) {
+
+ uid_t uid = -1;
+ const char *cc = NULL;
+ char *realm = NULL;
+ const char *principal_s = NULL;
+ const char *service = NULL;
+ BOOL internal_ccache = False;
+
+ uid = get_uid_from_state(state);
+ if (uid == -1) {
+ DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ cc = generate_krb5_ccache(state->mem_ctx,
+ state->request.data.auth.krb5_cc_type,
+ state->request.data.auth.uid,
+ &internal_ccache);
+ if (cc == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ realm = domain->alt_name;
+ strupper_m(realm);
+
+ principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm);
+ if (principal_s == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ service = talloc_asprintf(state->mem_ctx, "%s/%s@%s", KRB5_TGS_NAME, realm, realm);
+ if (service == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!internal_ccache) {
+
+ setup_return_cc_name(state, cc);
+
+ result = add_ccache_to_list(principal_s,
+ cc,
+ service,
+ state->request.data.auth.user,
+ domain->alt_name,
+ uid,
+ time(NULL),
+ time(NULL) + lp_winbind_cache_time(),
+ time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
+ True);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: failed "
+ "to add ccache to list: %s\n",
+ nt_errstr(result)));
+ }
+ }
+ }
+#endif /* HAVE_KRB5 */
+ success:
/* FIXME: we possibly should handle logon hours as well (does xp when
* offline?) see auth/auth_sam.c:sam_account_ok for details */
@@ -815,7 +971,8 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
state->request.data.auth.pass,
my_info3);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(1,("failed to update creds: %s\n", nt_errstr(result)));
+ DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
+ nt_errstr(result)));
return result;
}
@@ -916,7 +1073,7 @@ NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
}
if (!contact_domain->initialized) {
- set_dc_type_and_flags(contact_domain);
+ init_dc_connection(contact_domain);
}
if (!contact_domain->active_directory) {
@@ -1093,6 +1250,65 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
} while ( (attempts < 2) && retry );
+ /* handle the case where a NT4 DC does not fill in the acct_flags in
+ * the samlogon reply info3. When accurate info3 is required by the
+ * caller, we look up the account flags ourselve - gd */
+
+ if ((state->request.flags & WBFLAG_PAM_INFO3_TEXT) &&
+ (my_info3->acct_flags == 0) && NT_STATUS_IS_OK(result)) {
+
+ struct rpc_pipe_client *samr_pipe;
+ POLICY_HND samr_domain_handle, user_pol;
+ SAM_USERINFO_CTR *user_ctr;
+ NTSTATUS status_tmp;
+ uint32 acct_flags;
+
+ ZERO_STRUCT(user_ctr);
+
+ status_tmp = cm_connect_sam(contact_domain, state->mem_ctx,
+ &samr_pipe, &samr_domain_handle);
+
+ if (!NT_STATUS_IS_OK(status_tmp)) {
+ DEBUG(3, ("could not open handle to SAMR pipe: %s\n",
+ nt_errstr(status_tmp)));
+ goto done;
+ }
+
+ status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx,
+ &samr_domain_handle,
+ MAXIMUM_ALLOWED_ACCESS,
+ my_info3->user_rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(status_tmp)) {
+ DEBUG(3, ("could not open user handle on SAMR pipe: %s\n",
+ nt_errstr(status_tmp)));
+ goto done;
+ }
+
+ status_tmp = rpccli_samr_query_userinfo(samr_pipe, state->mem_ctx,
+ &user_pol, 16, &user_ctr);
+
+ if (!NT_STATUS_IS_OK(status_tmp)) {
+ DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
+ nt_errstr(status_tmp)));
+ rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ goto done;
+ }
+
+ acct_flags = user_ctr->info.id16->acb_info;
+
+ if (acct_flags == 0) {
+ rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ goto done;
+ }
+
+ my_info3->acct_flags = acct_flags;
+
+ DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags));
+
+ rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ }
+
*info3 = my_info3;
done:
return result;
@@ -1118,6 +1334,21 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+ if (domain->online == False) {
+ result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ if (domain->startup) {
+ /* Logons are very important to users. If we're offline and
+ we get a request within the first 30 seconds of startup,
+ try very hard to find a DC and go online. */
+
+ DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth "
+ "request in startup mode.\n", domain->name ));
+
+ winbindd_flush_negative_conn_cache(domain);
+ result = init_dc_connection(domain);
+ }
+ }
+
DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
/* Check for Kerberos authentication */
@@ -1204,7 +1435,7 @@ process_result:
DOM_SID user_sid;
- /* In all codepaths were result == NT_STATUS_OK info3 must have
+ /* In all codepaths where result == NT_STATUS_OK info3 must have
been initialized. */
if (!info3) {
result = NT_STATUS_INTERNAL_ERROR;
@@ -1245,29 +1476,74 @@ process_result:
}
- if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
- lp_winbind_offline_logon()) {
+ if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
+
+ /* Store in-memory creds for single-signon using ntlm_auth. */
+ result = winbindd_add_memory_creds(state->request.data.auth.user,
+ get_uid_from_state(state),
+ state->request.data.auth.pass);
- result = winbindd_store_creds(domain,
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result)));
+ goto done;
+ }
+
+ if (lp_winbind_offline_logon()) {
+ result = winbindd_store_creds(domain,
state->mem_ctx,
state->request.data.auth.user,
state->request.data.auth.pass,
info3, NULL);
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
- goto done;
+ if (!NT_STATUS_IS_OK(result)) {
+
+ /* Release refcount. */
+ winbindd_delete_memory_creds(state->request.data.auth.user);
+
+ DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+ goto done;
+ }
}
+ }
+ result = fillup_password_policy(domain, state);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+ goto done;
}
- result = fillup_password_policy(domain, state);
+ if (state->request.flags & WBFLAG_PAM_UNIX_NAME) {
+ /* We've been asked to return the unix username, per
+ 'winbind use default domain' settings and the like */
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+ fstring username_out;
+ const char *nt_username, *nt_domain;
+
+ if (!(nt_username = unistr2_tdup(state->mem_ctx, &info3->uni_user_name))) {
+ /* If the server didn't give us one, just use the one we sent them */
+ nt_username = name_user;
+ }
+
+ if (!(nt_domain = unistr2_tdup(state->mem_ctx, &info3->uni_logon_dom))) {
+ /* If the server didn't give us one, just use the one we sent them */
+ nt_domain = name_domain;
+ }
+
+ fill_domain_username(username_out, nt_domain, nt_username, True);
+
+ DEBUG(5, ("Setting unix username to [%s]\n", username_out));
+
+ SAFE_FREE(state->response.extra_data.data);
+ state->response.extra_data.data = SMB_STRDUP(username_out);
+ if (!state->response.extra_data.data) {
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
-
- }
+ state->response.length +=
+ strlen((const char *)state->response.extra_data.data)+1;
+ }
+ }
+
done:
/* give us a more useful (more correct?) error code */
@@ -1289,7 +1565,7 @@ done:
state->response.data.auth.nt_status_string,
state->response.data.auth.pam_error));
- if ( NT_STATUS_IS_OK(result) &&
+ if ( NT_STATUS_IS_OK(result) && info3 &&
(state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {
char *afsname = talloc_strdup(state->mem_ctx,
@@ -1341,14 +1617,15 @@ done:
state->response.extra_data.data =
afs_createtoken_str(afsname, cell);
- if (state->response.extra_data.data != NULL)
+ if (state->response.extra_data.data != NULL) {
state->response.length +=
- strlen(state->response.extra_data.data)+1;
+ strlen((const char *)state->response.extra_data.data)+1;
+ }
no_token:
TALLOC_FREE(afsname);
}
-
+
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
@@ -1593,7 +1870,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
result = NT_STATUS_NO_MEMORY;
goto done;
}
- state->response.length += strlen(state->response.extra_data.data)+1;
+ state->response.length +=
+ strlen((const char *)state->response.extra_data.data)+1;
}
if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
@@ -1641,29 +1919,54 @@ done:
void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- char *oldpass;
- char *newpass = NULL;
fstring domain, user;
- POLICY_HND dom_pol;
struct winbindd_domain *contact_domain;
- struct rpc_pipe_client *cli;
- BOOL got_info = False;
- SAM_UNK_INFO_1 info;
- SAMR_CHANGE_REJECT reject;
DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
state->request.data.chauthtok.user));
/* Setup crap */
- parse_domain_user(state->request.data.chauthtok.user, domain, user);
+ if (!canonicalize_username(state->request.data.chauthtok.user, domain, user)) {
+ set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
+ DEBUG(5, ("winbindd_pam_chauthtok: canonicalize_username %s failed with %s"
+ "(PAM: %d)\n",
+ state->request.data.auth.user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
+ request_error(state);
+ return;
+ }
contact_domain = find_domain_from_name(domain);
if (!contact_domain) {
+ set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
state->request.data.chauthtok.user, domain, user, domain));
- result = NT_STATUS_NO_SUCH_USER;
+ request_error(state);
+ return;
+ }
+
+ sendto_domain(state, contact_domain);
+}
+
+enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact_domain,
+ struct winbindd_cli_state *state)
+{
+ char *oldpass;
+ char *newpass = NULL;
+ POLICY_HND dom_pol;
+ struct rpc_pipe_client *cli;
+ BOOL got_info = False;
+ SAM_UNK_INFO_1 info;
+ SAMR_CHANGE_REJECT reject;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ fstring domain, user;
+
+ DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid,
+ state->request.data.auth.user));
+
+ if (!parse_domain_user(state->request.data.chauthtok.user, domain, user)) {
goto done;
}
@@ -1686,9 +1989,9 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject);
- /* FIXME: need to check for other error codes ? */
- if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
+ /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */
+ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) {
state->response.data.auth.policy.min_length_password =
info.min_length_password;
state->response.data.auth.policy.password_history =
@@ -1704,9 +2007,10 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
reject.reject_reason;
got_info = True;
+ }
/* only fallback when the chgpasswd3 call is not supported */
- } else if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) ||
+ if ((NT_STATUS_EQUAL(result, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR))) ||
(NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) ||
(NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) {
@@ -1714,20 +2018,36 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
nt_errstr(result)));
result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass);
+
+ /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION.
+ Map to the same status code as Windows 2003. */
+
+ if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) {
+ result = NT_STATUS_PASSWORD_RESTRICTION;
+ }
}
done:
- if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
- lp_winbind_offline_logon()) {
- NTSTATUS cred_ret;
+ if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
- cred_ret = winbindd_update_creds_by_name(contact_domain,
+ /* Update the single sign-on memory creds. */
+ result = winbindd_replace_memory_creds(state->request.data.chauthtok.user,
+ newpass);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result)));
+ goto process_result;
+ }
+
+ if (lp_winbind_offline_logon()) {
+ result = winbindd_update_creds_by_name(contact_domain,
state->mem_ctx, user,
newpass);
- if (!NT_STATUS_IS_OK(cred_ret)) {
- DEBUG(10,("Failed to store creds: %s\n", nt_errstr(cred_ret)));
- goto process_result; /* FIXME: hm, risking inconsistant cache ? */
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+ goto process_result;
+ }
}
}
@@ -1761,11 +2081,7 @@ process_result:
state->response.data.auth.nt_status_string,
state->response.data.auth.pam_error));
- if (NT_STATUS_IS_OK(result)) {
- request_ok(state);
- } else {
- request_error(state);
- }
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
void winbindd_pam_logoff(struct winbindd_cli_state *state)
@@ -1783,30 +2099,32 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
state->request.data.logoff.krb5ccname
[sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
- parse_domain_user(state->request.data.logoff.user, name_domain, user);
-
- domain = find_auth_domain(state, name_domain);
+ if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) {
+ goto failed;
+ }
- if (domain == NULL) {
- set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
- DEBUG(5, ("Pam Logoff for %s returned %s "
- "(PAM: %d)\n",
- state->request.data.logoff.user,
- state->response.data.auth.nt_status_string,
- state->response.data.auth.pam_error));
- request_error(state);
- return;
+ if ((domain = find_auth_domain(state, name_domain)) == NULL) {
+ goto failed;
}
sendto_domain(state, domain);
+ return;
+
+ failed:
+ set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
+ DEBUG(5, ("Pam Logoff for %s returned %s "
+ "(PAM: %d)\n",
+ state->request.data.logoff.user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
+ request_error(state);
+ return;
}
enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
- struct WINBINDD_CCACHE_ENTRY *entry;
- int ret;
DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid,
state->request.data.logoff.user));
@@ -1816,54 +2134,49 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
goto process_result;
}
-#ifdef HAVE_KRB5
-
- /* what we need here is to find the corresponding krb5 ccache name *we*
- * created for a given username and destroy it (as the user who created it) */
-
- entry = get_ccache_by_username(state->request.data.logoff.user);
- if (entry == NULL) {
- DEBUG(10,("winbindd_pam_logoff: could not get ccname for user %s\n",
- state->request.data.logoff.user));
+ if (state->request.data.logoff.krb5ccname[0] == '\0') {
+ result = NT_STATUS_OK;
goto process_result;
}
- DEBUG(10,("winbindd_pam_logoff: found ccache [%s]\n", entry->ccname));
-
- if (entry->uid < 0 || state->request.data.logoff.uid < 0) {
+#ifdef HAVE_KRB5
+
+ if (state->request.data.logoff.uid < 0) {
DEBUG(0,("winbindd_pam_logoff: invalid uid\n"));
goto process_result;
}
- if (entry->uid != state->request.data.logoff.uid) {
- DEBUG(0,("winbindd_pam_logoff: uid's differ: %d != %d\n",
- entry->uid, state->request.data.logoff.uid));
+ /* what we need here is to find the corresponding krb5 ccache name *we*
+ * created for a given username and destroy it */
+
+ if (!ccache_entry_exists(state->request.data.logoff.user)) {
+ result = NT_STATUS_OK;
+ DEBUG(10,("winbindd_pam_logoff: no entry found.\n"));
goto process_result;
}
- if (!strcsequal(entry->ccname, state->request.data.logoff.krb5ccname)) {
- DEBUG(0,("winbindd_pam_logoff: krb5ccnames differ: (daemon) %s != (client) %s\n",
- entry->ccname, state->request.data.logoff.krb5ccname));
+ if (!ccache_entry_identical(state->request.data.logoff.user,
+ state->request.data.logoff.uid,
+ state->request.data.logoff.krb5ccname)) {
+ DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n"));
goto process_result;
}
- ret = ads_kdestroy(entry->ccname);
-
- if (ret) {
- DEBUG(0,("winbindd_pam_logoff: failed to destroy user ccache %s with: %s\n",
- entry->ccname, error_message(ret)));
- } else {
- DEBUG(10,("winbindd_pam_logoff: successfully destroyed ccache %s for user %s\n",
- entry->ccname, state->request.data.logoff.user));
- remove_ccache_by_ccname(entry->ccname);
+ result = remove_ccache(state->request.data.logoff.user);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("winbindd_pam_logoff: failed to remove ccache: %s\n",
+ nt_errstr(result)));
+ goto process_result;
}
- result = krb5_to_nt_status(ret);
#else
result = NT_STATUS_NOT_SUPPORTED;
#endif
process_result:
+
+ winbindd_delete_memory_creds(state->request.data.logoff.user);
+
state->response.data.auth.nt_status = NT_STATUS_V(result);
fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
@@ -1872,3 +2185,158 @@ process_result:
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
+/* Change user password with auth crap*/
+
+void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain = NULL;
+ const char *domain_name = NULL;
+
+ /* Ensure null termination */
+ state->request.data.chng_pswd_auth_crap.user[
+ sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0;
+ state->request.data.chng_pswd_auth_crap.domain[
+ sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0;
+
+ DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
+ (unsigned long)state->pid,
+ state->request.data.chng_pswd_auth_crap.domain,
+ state->request.data.chng_pswd_auth_crap.user));
+
+ if (*state->request.data.chng_pswd_auth_crap.domain != '\0') {
+ domain_name = state->request.data.chng_pswd_auth_crap.domain;
+ } else if (lp_winbind_use_default_domain()) {
+ domain_name = lp_workgroup();
+ }
+
+ if (domain_name != NULL)
+ domain = find_domain_from_name(domain_name);
+
+ if (domain != NULL) {
+ DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: "
+ "%s\n", (unsigned long)state->pid,domain->name));
+ sendto_domain(state, domain);
+ return;
+ }
+
+ set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
+ DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n",
+ state->request.data.chng_pswd_auth_crap.domain,
+ state->request.data.chng_pswd_auth_crap.user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
+ request_error(state);
+ return;
+}
+
+enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state)
+{
+ NTSTATUS result;
+ DATA_BLOB new_nt_password;
+ DATA_BLOB old_nt_hash_enc;
+ DATA_BLOB new_lm_password;
+ DATA_BLOB old_lm_hash_enc;
+ fstring domain,user;
+ POLICY_HND dom_pol;
+ struct winbindd_domain *contact_domain = domainSt;
+ struct rpc_pipe_client *cli;
+
+ /* Ensure null termination */
+ state->request.data.chng_pswd_auth_crap.user[
+ sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0;
+ state->request.data.chng_pswd_auth_crap.domain[
+ sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0;
+ *domain = 0;
+ *user = 0;
+
+ DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
+ (unsigned long)state->pid,
+ state->request.data.chng_pswd_auth_crap.domain,
+ state->request.data.chng_pswd_auth_crap.user));
+
+ if (lp_winbind_offline_logon()) {
+ DEBUG(0,("Refusing password change as winbind offline logons are enabled. "));
+ DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n"));
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ if (*state->request.data.chng_pswd_auth_crap.domain) {
+ fstrcpy(domain,state->request.data.chng_pswd_auth_crap.domain);
+ } else {
+ parse_domain_user(state->request.data.chng_pswd_auth_crap.user,
+ domain, user);
+
+ if(!*domain) {
+ DEBUG(3,("no domain specified with username (%s) - "
+ "failing auth\n",
+ state->request.data.chng_pswd_auth_crap.user));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+ }
+
+ if (!*domain && lp_winbind_use_default_domain()) {
+ fstrcpy(domain,(char *)lp_workgroup());
+ }
+
+ if(!*user) {
+ fstrcpy(user, state->request.data.chng_pswd_auth_crap.user);
+ }
+
+ DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n",
+ (unsigned long)state->pid, domain, user));
+
+ /* Change password */
+ new_nt_password = data_blob_talloc(
+ state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.new_nt_pswd,
+ state->request.data.chng_pswd_auth_crap.new_nt_pswd_len);
+
+ old_nt_hash_enc = data_blob_talloc(
+ state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.old_nt_hash_enc,
+ state->request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
+
+ if(state->request.data.chng_pswd_auth_crap.new_lm_pswd_len > 0) {
+ new_lm_password = data_blob_talloc(
+ state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.new_lm_pswd,
+ state->request.data.chng_pswd_auth_crap.new_lm_pswd_len);
+
+ old_lm_hash_enc = data_blob_talloc(
+ state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.old_lm_hash_enc,
+ state->request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
+ } else {
+ new_lm_password.length = 0;
+ old_lm_hash_enc.length = 0;
+ }
+
+ /* Get sam handle */
+
+ result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
+ goto done;
+ }
+
+ result = rpccli_samr_chng_pswd_auth_crap(
+ cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc,
+ new_lm_password, old_lm_hash_enc);
+
+ done:
+ state->response.data.auth.nt_status = NT_STATUS_V(result);
+ fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
+ fstrcpy(state->response.data.auth.error_string,
+ get_friendly_nt_error_msg(result));
+ state->response.data.auth.pam_error = nt_status_to_pam(result);
+
+ DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
+ ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
+ domain, user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
+
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+}
diff --git a/source/nsswitch/winbindd_passdb.c b/source/nsswitch/winbindd_passdb.c
index b949ea08085..cd081d65175 100644
--- a/source/nsswitch/winbindd_passdb.c
+++ b/source/nsswitch/winbindd_passdb.c
@@ -28,151 +28,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-static void add_member(const char *domain, const char *user,
- char **pp_members, size_t *p_num_members)
-{
- fstring name;
-
- fill_domain_username(name, domain, user, True);
- safe_strcat(name, ",", sizeof(name)-1);
- string_append(pp_members, name);
- *p_num_members += 1;
-}
-
-/**********************************************************************
- Add member users resulting from sid. Expand if it is a domain group.
-**********************************************************************/
-
-static void add_expanded_sid(const DOM_SID *sid, char **pp_members, size_t *p_num_members)
-{
- DOM_SID dom_sid;
- uint32 rid;
- struct winbindd_domain *domain;
- size_t i;
-
- char *domain_name = NULL;
- char *name = NULL;
- enum SID_NAME_USE type;
-
- uint32 num_names;
- DOM_SID *sid_mem;
- char **names;
- uint32 *types;
-
- NTSTATUS result;
-
- TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
-
- if (mem_ctx == NULL) {
- DEBUG(1, ("talloc_init failed\n"));
- return;
- }
-
- sid_copy(&dom_sid, sid);
- sid_split_rid(&dom_sid, &rid);
-
- domain = find_lookup_domain_from_sid(sid);
-
- if (domain == NULL) {
- DEBUG(3, ("Could not find domain for sid %s\n",
- sid_string_static(sid)));
- goto done;
- }
-
- result = domain->methods->sid_to_name(domain, mem_ctx, sid,
- &domain_name, &name, &type);
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(3, ("sid_to_name failed for sid %s\n",
- sid_string_static(sid)));
- goto done;
- }
-
- DEBUG(10, ("Found name %s, type %d\n", name, type));
-
- if (type == SID_NAME_USER) {
- add_member(domain_name, name, pp_members, p_num_members);
- goto done;
- }
-
- if (type != SID_NAME_DOM_GRP) {
- DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
- name));
- goto done;
- }
-
- /* Expand the domain group, this must be done via the target domain */
-
- domain = find_domain_from_sid(sid);
-
- if (domain == NULL) {
- DEBUG(3, ("Could not find domain from SID %s\n",
- sid_string_static(sid)));
- goto done;
- }
-
- result = domain->methods->lookup_groupmem(domain, mem_ctx,
- sid, &num_names,
- &sid_mem, &names,
- &types);
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10, ("Could not lookup group members for %s: %s\n",
- name, nt_errstr(result)));
- goto done;
- }
-
- for (i=0; i<num_names; i++) {
- DEBUG(10, ("Adding group member SID %s\n",
- sid_string_static(&sid_mem[i])));
-
- if (types[i] != SID_NAME_USER) {
- DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
- "Ignoring.\n", names[i], name));
- continue;
- }
-
- add_member(domain->name, names[i], pp_members, p_num_members);
- }
-
- done:
- talloc_destroy(mem_ctx);
- return;
-}
-
-BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
- DOM_SID *group_sid,
- size_t *num_gr_mem, char **gr_mem, size_t *gr_mem_len)
-{
- DOM_SID *members;
- size_t i, num_members;
-
- *num_gr_mem = 0;
- *gr_mem = NULL;
- *gr_mem_len = 0;
-
- if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
- &num_members)))
- return True;
-
- for (i=0; i<num_members; i++) {
- add_expanded_sid(&members[i], gr_mem, num_gr_mem);
- }
-
- SAFE_FREE(members);
-
- if (*gr_mem != NULL) {
- size_t len;
-
- /* We have at least one member, strip off the last "," */
- len = strlen(*gr_mem);
- (*gr_mem)[len-1] = '\0';
- *gr_mem_len = len;
- }
-
- return True;
-}
-
/* Query display info for a domain. This returns enough information plus a
bit extra to give an overview of domain users for the User Manager
application. */
@@ -241,7 +96,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
DEBUG(10, ("Finding name %s\n", name));
@@ -262,7 +117,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
const DOM_SID *sid,
char **domain_name,
char **name,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
const char *dom, *nam;
@@ -286,6 +141,18 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ uint32 *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types)
+{
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -353,15 +220,21 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
const DOM_SID **sids;
struct lsa_dom_info *lsa_domains;
struct lsa_name_info *lsa_names;
+ TALLOC_CTX *tmp_ctx;
if (!sid_check_is_in_our_domain(group_sid)) {
/* There's no groups, only aliases in BUILTIN */
return NT_STATUS_NO_SUCH_GROUP;
}
- result = pdb_enum_group_members(mem_ctx, group_sid, &rids,
+ if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
&num_members);
if (!NT_STATUS_IS_OK(result)) {
+ TALLOC_FREE(tmp_ctx);
return result;
}
@@ -370,29 +243,39 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
*sid_mem = NULL;
*names = NULL;
*name_types = NULL;
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
}
*sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
*names = TALLOC_ARRAY(mem_ctx, char *, num_members);
*name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
- sids = TALLOC_ARRAY(mem_ctx, const DOM_SID *, num_members);
+ sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
if (((*sid_mem) == NULL) || ((*names) == NULL) ||
((*name_types) == NULL) || (sids == NULL)) {
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
+ /*
+ * Prepare an array of sid pointers for the lookup_sids calling
+ * convention.
+ */
+
for (i=0; i<num_members; i++) {
DOM_SID *sid = &((*sid_mem)[i]);
- sid_copy(sid, &domain->sid);
- sid_append_rid(sid, rids[i]);
+ if (!sid_compose(sid, &domain->sid, rids[i])) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
sids[i] = sid;
}
- result = lookup_sids(mem_ctx, num_members, sids, 1,
+ result = lookup_sids(tmp_ctx, num_members, sids, 1,
&lsa_domains, &lsa_names);
if (!NT_STATUS_IS_OK(result)) {
+ TALLOC_FREE(tmp_ctx);
return result;
}
@@ -403,8 +286,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
sid_type_lookup(lsa_names[i].type)));
continue;
}
- (*names)[i] = talloc_steal((*names),
- lsa_names[i].name);
+ if (!((*names)[i] = talloc_strdup((*names),
+ lsa_names[i].name))) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
(*name_types)[i] = lsa_names[i].type;
num_mapped += 1;
@@ -412,6 +299,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
*num_names = num_mapped;
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
}
@@ -497,15 +385,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
NTSTATUS nt_status;
struct trustdom_info **domains;
int i;
+ TALLOC_CTX *tmp_ctx;
*num_domains = 0;
*names = NULL;
*alt_names = NULL;
*dom_sids = NULL;
- nt_status = secrets_trusted_domains(mem_ctx, num_domains,
+ if (!(tmp_ctx = talloc_init("trusted_domains"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = secrets_trusted_domains(tmp_ctx, num_domains,
&domains);
if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE(tmp_ctx);
return nt_status;
}
@@ -514,15 +408,21 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
for (i=0; i<*num_domains; i++) {
(*alt_names)[i] = NULL;
- (*names)[i] = talloc_steal((*names), domains[i]->name);
+ if (!((*names)[i] = talloc_strdup((*names),
+ domains[i]->name))) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
sid_copy(&(*dom_sids)[i], &domains[i]->sid);
}
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
}
@@ -534,6 +434,7 @@ struct winbindd_methods passdb_methods = {
enum_local_groups,
name_to_sid,
sid_to_name,
+ rids_to_names,
query_user,
lookup_usergroups,
lookup_useraliases,
diff --git a/source/nsswitch/winbindd_reconnect.c b/source/nsswitch/winbindd_reconnect.c
index 7bc8be12131..6b484bdd062 100644
--- a/source/nsswitch/winbindd_reconnect.c
+++ b/source/nsswitch/winbindd_reconnect.c
@@ -87,7 +87,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
NTSTATUS result;
@@ -111,7 +111,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
const DOM_SID *sid,
char **domain_name,
char **name,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
NTSTATUS result;
@@ -125,6 +125,30 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
return result;
}
+static NTSTATUS rids_to_names(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ uint32 *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types)
+{
+ NTSTATUS result;
+
+ result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+ rids, num_rids,
+ domain_name, names, types);
+ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
+ result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+ rids, num_rids,
+ domain_name, names,
+ types);
+ }
+
+ return result;
+}
+
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -280,6 +304,7 @@ struct winbindd_methods reconnect_methods = {
enum_local_groups,
name_to_sid,
sid_to_name,
+ rids_to_names,
query_user,
lookup_usergroups,
lookup_useraliases,
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 19ae5221ccd..11d9fe0dbbd 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -241,12 +241,12 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
const char *domain_name,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
NTSTATUS result;
DOM_SID *sids = NULL;
- uint32 *types = NULL;
- const char *full_name;
+ enum lsa_SidType *types = NULL;
+ char *full_name = NULL;
struct rpc_pipe_client *cli;
POLICY_HND lsa_policy;
@@ -262,6 +262,8 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
return NT_STATUS_NO_MEMORY;
}
+ ws_name_return( full_name, '_' );
+
DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
@@ -269,7 +271,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
return result;
result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
- &full_name, NULL, &sids, &types);
+ (const char**) &full_name, NULL, &sids, &types);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -277,7 +279,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
/* Return rid and type if lookup successful */
sid_copy(sid, &sids[0]);
- *type = (enum SID_NAME_USE)types[0];
+ *type = types[0];
return NT_STATUS_OK;
}
@@ -290,11 +292,11 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
const DOM_SID *sid,
char **domain_name,
char **name,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
char **domains;
char **names;
- uint32 *types;
+ enum lsa_SidType *types;
NTSTATUS result;
struct rpc_pipe_client *cli;
POLICY_HND lsa_policy;
@@ -311,13 +313,70 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
if (!NT_STATUS_IS_OK(result))
return result;
- *type = (enum SID_NAME_USE)types[0];
+ *type = (enum lsa_SidType)types[0];
*domain_name = domains[0];
*name = names[0];
+
+ ws_name_replace( *name, '_' );
+
DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
return NT_STATUS_OK;
}
+NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ uint32 *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types)
+{
+ char **domains;
+ NTSTATUS result;
+ struct rpc_pipe_client *cli;
+ POLICY_HND lsa_policy;
+ DOM_SID *sids;
+ size_t i;
+ char **ret_names;
+
+ DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
+
+ sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
+ if (sids == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_rids; i++) {
+ if (!sid_compose(&sids[i], sid, rids[i])) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
+ num_rids, sids, &domains,
+ names, types);
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+ return result;
+ }
+
+ ret_names = *names;
+ for (i=0; i<num_rids; i++) {
+ if ((*types)[i] != SID_NAME_UNKNOWN) {
+ ws_name_replace( ret_names[i], '_' );
+ *domain_name = domains[i];
+ }
+ }
+
+ return result;
+}
+
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -332,7 +391,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
NET_USER_INFO_3 *user;
struct rpc_pipe_client *cli;
- DEBUG(3,("rpc: query_user rid=%s\n",
+ DEBUG(3,("rpc: query_user sid=%s\n",
sid_to_string(sid_string, user_sid)));
if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
@@ -357,6 +416,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
user_info->homedir = NULL;
user_info->shell = NULL;
+ user_info->primary_gid = (gid_t)-1;
SAFE_FREE(user);
@@ -395,6 +455,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
&ctr->info.id21->uni_full_name);
user_info->homedir = NULL;
user_info->shell = NULL;
+ user_info->primary_gid = (gid_t)-1;
return NT_STATUS_OK;
}
@@ -528,8 +589,10 @@ NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
for (i=0; i<num_aliases_query; i++) {
size_t na = *num_aliases;
- add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
- alias_rids, &na);
+ if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
+ alias_rids, &na)) {
+ return NT_STATUS_NO_MEMORY;
+ }
*num_aliases = na;
}
@@ -721,53 +784,20 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
/**********************************************************************
Get the sequence number for a Windows AD native mode domain using
- LDAP queries
+ LDAP queries.
**********************************************************************/
-static int get_ldap_sequence_number( const char* domain, uint32 *seq)
+static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
int ret = -1;
- int i, port = LDAP_PORT;
- struct ip_service *ip_list = NULL;
- int count;
-
- if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
- DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
- return False;
- }
-
- /* Finally return first DC that we can contact */
-
- for (i = 0; i < count; i++) {
- fstring ipstr;
+ fstring ipstr;
- /* since the is an LDAP lookup, default to the LDAP_PORT is
- * not set */
- port = (ip_list[i].port!= PORT_NONE) ?
- ip_list[i].port : LDAP_PORT;
-
- fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
-
- if (is_zero_ip(ip_list[i].ip))
- continue;
-
- if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 )
- goto done;
-
- /* add to failed connection cache */
- add_failed_connection_entry( domain, ipstr,
- NT_STATUS_UNSUCCESSFUL );
- }
-
-done:
- if ( ret == 0 ) {
+ fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
+ if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
- "number for Domain (%s) from DC (%s:%d)\n",
- domain, inet_ntoa(ip_list[i].ip), port));
- }
-
- SAFE_FREE(ip_list);
-
+ "number for Domain (%s) from DC (%s)\n",
+ domain->name, ipstr));
+ }
return ret;
}
@@ -781,7 +811,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
NTSTATUS result;
POLICY_HND dom_pol;
BOOL got_seq_num = False;
- int retry;
struct rpc_pipe_client *cli;
DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
@@ -791,8 +820,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
return NT_STATUS_NO_MEMORY;
- retry = 0;
-
#ifdef HAVE_LDAP
if ( domain->native_mode )
{
@@ -801,7 +828,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
DEBUG(8,("using get_ldap_seq() to retrieve the "
"sequence number\n"));
- res = get_ldap_sequence_number( domain->name, seq );
+ res = get_ldap_sequence_number( domain, seq );
if (res == 0)
{
result = NT_STATUS_OK;
@@ -827,7 +854,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
if (NT_STATUS_IS_OK(result)) {
- *seq = ctr.info.inf8.seq_num.low;
+ *seq = ctr.info.inf8.seq_num;
got_seq_num = True;
goto seq_num;
}
@@ -838,7 +865,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
if (NT_STATUS_IS_OK(result)) {
- *seq = ctr.info.inf2.seq_num.low;
+ *seq = ctr.info.inf2.seq_num;
got_seq_num = True;
}
@@ -994,6 +1021,7 @@ struct winbindd_methods msrpc_methods = {
enum_local_groups,
msrpc_name_to_sid,
msrpc_sid_to_name,
+ msrpc_rids_to_names,
query_user,
lookup_usergroups,
msrpc_lookup_useraliases,
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index a715f82c790..13b2cd05550 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -30,7 +30,7 @@
static void lookupsid_recv(void *private_data, BOOL success,
const char *dom_name, const char *name,
- enum SID_NAME_USE type);
+ enum lsa_SidType type);
void winbindd_lookupsid(struct winbindd_cli_state *state)
{
@@ -53,7 +53,7 @@ void winbindd_lookupsid(struct winbindd_cli_state *state)
static void lookupsid_recv(void *private_data, BOOL success,
const char *dom_name, const char *name,
- enum SID_NAME_USE type)
+ enum lsa_SidType type)
{
struct winbindd_cli_state *state =
talloc_get_type_abort(private_data, struct winbindd_cli_state);
@@ -75,7 +75,7 @@ static void lookupsid_recv(void *private_data, BOOL success,
**/
static void lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type);
+ const DOM_SID *sid, enum lsa_SidType type);
void winbindd_lookupname(struct winbindd_cli_state *state)
{
@@ -107,7 +107,7 @@ void winbindd_lookupname(struct winbindd_cli_state *state)
}
static void lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type)
+ const DOM_SID *sid, enum lsa_SidType type)
{
struct winbindd_cli_state *state =
talloc_get_type_abort(private_data, struct winbindd_cli_state);
@@ -124,6 +124,34 @@ static void lookupname_recv(void *private_data, BOOL success,
return;
}
+void winbindd_lookuprids(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ DOM_SID domain_sid;
+
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
+ DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid));
+
+ if (!string_to_sid(&domain_sid, state->request.data.sid)) {
+ DEBUG(5, ("Could not convert %s to SID\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ domain = find_lookup_domain_from_sid(&domain_sid);
+ if (domain == NULL) {
+ DEBUG(10, ("Could not find domain for name %s\n",
+ state->request.domain_name));
+ request_error(state);
+ return;
+ }
+
+ sendto_domain(state, domain);
+}
+
static struct winbindd_child static_idmap_child;
void init_idmap_child(void)
@@ -139,12 +167,25 @@ struct winbindd_child *idmap_child(void)
/* Convert a sid to a uid. We assume we only have one rid attached to the
sid. */
-static void sid2uid_recv(void *private_data, BOOL success, uid_t uid);
+static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
+
+ if (!success) {
+ DEBUG(5, ("Could not convert sid %s\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ state->response.data.uid = uid;
+ request_ok(state);
+}
void winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -152,12 +193,6 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
state->request.data.sid));
- if (idmap_proxyonly()) {
- DEBUG(8, ("IDMAP proxy only\n"));
- request_error(state);
- return;
- }
-
if (!string_to_sid(&sid, state->request.data.sid)) {
DEBUG(1, ("Could not get convert sid %s from string\n",
state->request.data.sid));
@@ -165,20 +200,14 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state)
return;
}
- /* Query only the local tdb, everything else might possibly block */
-
- result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
- ID_QUERY_ONLY|ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(result)) {
- request_ok(state);
- return;
- }
-
+ /* always use the async interface (may block) */
winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
}
-static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
+/* Convert a sid to a gid. We assume we only have one rid attached to the
+ sid.*/
+
+static void sid2gid_recv(void *private_data, BOOL success, gid_t gid)
{
struct winbindd_cli_state *state =
talloc_get_type_abort(private_data, struct winbindd_cli_state);
@@ -190,19 +219,13 @@ static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
return;
}
- state->response.data.uid = uid;
+ state->response.data.gid = gid;
request_ok(state);
}
-/* Convert a sid to a gid. We assume we only have one rid attached to the
- sid.*/
-
-static void sid2gid_recv(void *private_data, BOOL success, gid_t gid);
-
void winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -210,12 +233,6 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
state->request.data.sid));
- if (idmap_proxyonly()) {
- DEBUG(8, ("IDMAP proxy only\n"));
- request_error(state);
- return;
- }
-
if (!string_to_sid(&sid, state->request.data.sid)) {
DEBUG(1, ("Could not get convert sid %s from string\n",
state->request.data.sid));
@@ -223,229 +240,145 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state)
return;
}
- /* Query only the local tdb, everything else might possibly block */
-
- result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
- ID_QUERY_ONLY|ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(result)) {
- request_ok(state);
- return;
- }
-
+ /* always use the async interface (may block) */
winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
}
-static void sid2gid_recv(void *private_data, BOOL success, gid_t gid)
+static void sids2xids_recv(void *private_data, BOOL success, void *data, int len)
{
struct winbindd_cli_state *state =
talloc_get_type_abort(private_data, struct winbindd_cli_state);
if (!success) {
- DEBUG(5, ("Could not convert sid %s\n",
- state->request.data.sid));
+ DEBUG(5, ("Could not convert sids to xids\n"));
request_error(state);
return;
}
- state->response.data.gid = gid;
+ state->response.extra_data.data = data;
+ state->response.length = sizeof(state->response) + len;
request_ok(state);
}
-/* Convert a uid to a sid */
-
-struct uid2sid_state {
- struct winbindd_cli_state *cli_state;
- uid_t uid;
- fstring name;
- DOM_SID sid;
- enum SID_NAME_USE type;
-};
-
-static void uid2sid_uid2name_recv(void *private_data, BOOL success,
- const char *username);
-static void uid2sid_lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid,
- enum SID_NAME_USE type);
-static void uid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
+void winbindd_sids_to_unixids(struct winbindd_cli_state *state)
+{
+ DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid));
-static void uid2sid_recv(void *private_data, BOOL success, const char *sid);
+ winbindd_sids2xids_async(state->mem_ctx,
+ state->request.extra_data.data,
+ state->request.extra_len,
+ sids2xids_recv, state);
+}
-void winbindd_uid_to_sid(struct winbindd_cli_state *state)
+static void set_mapping_recv(void *private_data, BOOL success)
{
- DOM_SID sid;
- NTSTATUS status;
-
- DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
- (unsigned long)state->request.data.uid));
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
- if (idmap_proxyonly()) {
- DEBUG(8, ("IDMAP proxy only\n"));
+ if (!success) {
+ DEBUG(5, ("Could not set sid mapping\n"));
request_error(state);
return;
}
- status = idmap_uid_to_sid(&sid, state->request.data.uid,
- ID_QUERY_ONLY | ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(status)) {
- sid_to_string(state->response.data.sid.sid, &sid);
- state->response.data.sid.type = SID_NAME_USER;
- request_ok(state);
- return;
- }
-
- winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
+ request_ok(state);
}
-static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
+void winbindd_set_mapping(struct winbindd_cli_state *state)
{
- struct winbindd_cli_state *state = private_data;
- struct uid2sid_state *uid2sid_state;
-
- if (success) {
- DEBUG(10,("uid2sid: uid %lu has sid %s\n",
- (unsigned long)(state->request.data.uid), sid));
- fstrcpy(state->response.data.sid.sid, sid);
- state->response.data.sid.type = SID_NAME_USER;
- request_ok(state);
- return;
- }
-
- /* preexisitng mapping not found go on */
-
- if (is_in_uid_range(state->request.data.uid)) {
- /* This is winbind's, so we should better have succeeded
- * above. */
- request_error(state);
- return;
- }
+ struct id_map map;
+ DOM_SID sid;
- /* The only chance that this is correct is that winbind trusted
- * domains only = yes, and the user exists in nss and the domain. */
+ DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid));
- if (!lp_winbind_trusted_domains_only()) {
+ if ( ! state->privileged) {
+ DEBUG(0, ("Only root is allowed to set mappings!\n"));
request_error(state);
return;
}
- uid2sid_state = TALLOC_ZERO_P(state->mem_ctx, struct uid2sid_state);
- if (uid2sid_state == NULL) {
- DEBUG(0, ("talloc failed\n"));
+ if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ state->request.data.sid));
request_error(state);
return;
}
- uid2sid_state->cli_state = state;
- uid2sid_state->uid = state->request.data.uid;
+ map.sid = &sid;
+ map.xid.id = state->request.data.dual_idmapset.id;
+ map.xid.type = state->request.data.dual_idmapset.type;
- winbindd_uid2name_async(state->mem_ctx, state->request.data.uid,
- uid2sid_uid2name_recv, uid2sid_state);
+ winbindd_set_mapping_async(state->mem_ctx, &map,
+ set_mapping_recv, state);
}
-static void uid2sid_uid2name_recv(void *private_data, BOOL success,
- const char *username)
+static void set_hwm_recv(void *private_data, BOOL success)
{
- struct uid2sid_state *state =
- talloc_get_type_abort(private_data, struct uid2sid_state);
-
- DEBUG(10, ("uid2sid: uid %lu has name %s\n",
- (unsigned long)state->uid, username));
-
- fstrcpy(state->name, username);
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
if (!success) {
- request_error(state->cli_state);
+ DEBUG(5, ("Could not set sid mapping\n"));
+ request_error(state);
return;
}
- winbindd_lookupname_async(state->cli_state->mem_ctx,
- find_our_domain()->name, username,
- uid2sid_lookupname_recv, state);
+ request_ok(state);
}
-static void uid2sid_lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type)
+void winbindd_set_hwm(struct winbindd_cli_state *state)
{
- struct uid2sid_state *state =
- talloc_get_type_abort(private_data, struct uid2sid_state);
- unid_t id;
+ struct unixid xid;
+
+ DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid));
- if ((!success) || (type != SID_NAME_USER)) {
- request_error(state->cli_state);
+ if ( ! state->privileged) {
+ DEBUG(0, ("Only root is allowed to set mappings!\n"));
+ request_error(state);
return;
}
- state->sid = *sid;
- state->type = type;
+ xid.id = state->request.data.dual_idmapset.id;
+ xid.type = state->request.data.dual_idmapset.type;
- id.uid = state->uid;
- idmap_set_mapping_async(state->cli_state->mem_ctx, sid, id, ID_USERID,
- uid2sid_idmap_set_mapping_recv, state );
+ winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
}
-static void uid2sid_idmap_set_mapping_recv(void *private_data, BOOL success)
-{
- struct uid2sid_state *state =
- talloc_get_type_abort(private_data, struct uid2sid_state);
-
- /* don't fail if we can't store it */
-
- sid_to_string(state->cli_state->response.data.sid.sid, &state->sid);
- state->cli_state->response.data.sid.type = state->type;
- request_ok(state->cli_state);
-}
-
-/* Convert a gid to a sid */
-
-struct gid2sid_state {
- struct winbindd_cli_state *cli_state;
- gid_t gid;
- fstring name;
- DOM_SID sid;
- enum SID_NAME_USE type;
-};
-
-static void gid2sid_gid2name_recv(void *private_data, BOOL success,
- const char *groupname);
-static void gid2sid_lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid,
- enum SID_NAME_USE type);
-static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
-
-static void gid2sid_recv(void *private_data, BOOL success, const char *sid);
+/* Convert a uid to a sid */
-void winbindd_gid_to_sid(struct winbindd_cli_state *state)
+static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
{
- DOM_SID sid;
- NTSTATUS status;
-
- DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
- (unsigned long)state->request.data.gid));
+ struct winbindd_cli_state *state =
+ (struct winbindd_cli_state *)private_data;
- if (idmap_proxyonly()) {
- DEBUG(8, ("IDMAP proxy only\n"));
- request_error(state);
+ if (success) {
+ DEBUG(10,("uid2sid: uid %lu has sid %s\n",
+ (unsigned long)(state->request.data.uid), sid));
+ fstrcpy(state->response.data.sid.sid, sid);
+ state->response.data.sid.type = SID_NAME_USER;
+ request_ok(state);
return;
}
- status = idmap_gid_to_sid(&sid, state->request.data.gid,
- ID_QUERY_ONLY | ID_CACHE_ONLY);
+ request_error(state);
+ return;
+}
- if (NT_STATUS_IS_OK(status)) {
- sid_to_string(state->response.data.sid.sid, &sid);
- state->response.data.sid.type = SID_NAME_DOM_GRP;
- request_ok(state);
- return;
- }
+void winbindd_uid_to_sid(struct winbindd_cli_state *state)
+{
+ DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
+ (unsigned long)state->request.data.uid));
- winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
+ /* always go via the async interface (may block) */
+ winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
}
+/* Convert a gid to a sid */
+
static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
{
- struct winbindd_cli_state *state = private_data;
- struct gid2sid_state *gid2sid_state;
+ struct winbindd_cli_state *state =
+ (struct winbindd_cli_state *)private_data;
if (success) {
DEBUG(10,("gid2sid: gid %lu has sid %s\n",
@@ -456,91 +389,18 @@ static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
return;
}
- /* preexisitng mapping not found go on */
-
- if (is_in_gid_range(state->request.data.gid)) {
- /* This is winbind's, so we should better have succeeded
- * above. */
- request_error(state);
- return;
- }
-
- /* The only chance that this is correct is that winbind trusted
- * domains only = yes, and the user exists in nss and the domain. */
-
- if (!lp_winbind_trusted_domains_only()) {
- request_error(state);
- return;
- }
-
- /* The only chance that this is correct is that winbind trusted
- * domains only = yes, and the user exists in nss and the domain. */
-
- gid2sid_state = TALLOC_ZERO_P(state->mem_ctx, struct gid2sid_state);
- if (gid2sid_state == NULL) {
- DEBUG(0, ("talloc failed\n"));
- request_error(state);
- return;
- }
-
- gid2sid_state->cli_state = state;
- gid2sid_state->gid = state->request.data.gid;
-
- winbindd_gid2name_async(state->mem_ctx, state->request.data.gid,
- gid2sid_gid2name_recv, gid2sid_state);
-}
-
-static void gid2sid_gid2name_recv(void *private_data, BOOL success,
- const char *username)
-{
- struct gid2sid_state *state =
- talloc_get_type_abort(private_data, struct gid2sid_state);
-
- DEBUG(10, ("gid2sid: gid %lu has name %s\n",
- (unsigned long)state->gid, username));
-
- fstrcpy(state->name, username);
-
- if (!success) {
- request_error(state->cli_state);
- return;
- }
-
- winbindd_lookupname_async(state->cli_state->mem_ctx,
- find_our_domain()->name, username,
- gid2sid_lookupname_recv, state);
+ request_error(state);
+ return;
}
-static void gid2sid_lookupname_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type)
-{
- struct gid2sid_state *state =
- talloc_get_type_abort(private_data, struct gid2sid_state);
- unid_t id;
-
- if ((!success) ||
- ((type != SID_NAME_DOM_GRP) && (type!=SID_NAME_ALIAS))) {
- request_error(state->cli_state);
- return;
- }
-
- state->sid = *sid;
- state->type = type;
- id.gid = state->gid;
- idmap_set_mapping_async(state->cli_state->mem_ctx, sid, id, ID_GROUPID,
- gid2sid_idmap_set_mapping_recv, state );
-}
-
-static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success)
+void winbindd_gid_to_sid(struct winbindd_cli_state *state)
{
- struct gid2sid_state *state = private_data;
-
- /* don't fail if we can't store it */
+ DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
+ (unsigned long)state->request.data.gid));
- sid_to_string(state->cli_state->response.data.sid.sid, &state->sid);
- state->cli_state->response.data.sid.type = state->type;
- request_ok(state->cli_state);
+ /* always use async calls (may block) */
+ winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
}
void winbindd_allocate_uid(struct winbindd_cli_state *state)
@@ -558,12 +418,12 @@ void winbindd_allocate_uid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- union unid_t id;
+ struct unixid xid;
- if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_USERID))) {
+ if (!NT_STATUS_IS_OK(idmap_allocate_uid(&xid))) {
return WINBINDD_ERROR;
}
- state->response.data.uid = id.uid;
+ state->response.data.uid = xid.id;
return WINBINDD_OK;
}
@@ -582,12 +442,42 @@ void winbindd_allocate_gid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- union unid_t id;
+ struct unixid xid;
- if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_GROUPID))) {
+ if (!NT_STATUS_IS_OK(idmap_allocate_gid(&xid))) {
return WINBINDD_ERROR;
}
- state->response.data.gid = id.gid;
+ state->response.data.gid = xid.id;
return WINBINDD_OK;
}
+static void dump_maps_recv(void *private_data, BOOL success)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
+
+ if (!success) {
+ DEBUG(5, ("Could not dump maps\n"));
+ request_error(state);
+ return;
+ }
+
+ request_ok(state);
+}
+
+void winbindd_dump_maps(struct winbindd_cli_state *state)
+{
+ if ( ! state->privileged) {
+ DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n"));
+ request_error(state);
+ return;
+ }
+
+ DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid));
+
+ winbindd_dump_maps_async(state->mem_ctx,
+ state->request.extra_data.data,
+ state->request.extra_len,
+ dump_maps_recv, state);
+}
+
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 951fe319bdd..9df3a6a3bc1 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -28,8 +28,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-extern userdom_struct current_user_info;
-
static BOOL fillup_pw_field(const char *lp_template,
const char *username,
const char *domname,
@@ -43,7 +41,7 @@ static BOOL fillup_pw_field(const char *lp_template,
if (out == NULL)
return False;
- if (in && !strequal(in,"") && lp_security() == SEC_ADS && (get_nss_info(domname))) {
+ if ( in && !strequal(in,"") && lp_security() == SEC_ADS ) {
safe_strcpy(out, in, sizeof(fstring) - 1);
return True;
}
@@ -53,15 +51,16 @@ static BOOL fillup_pw_field(const char *lp_template,
shell. */
/* The substitution of %U and %D in the 'template homedir' is done
- by alloc_sub_specified() below. */
+ by talloc_sub_specified() below. */
- templ = alloc_sub_specified(lp_template, username, domname, uid, gid);
+ templ = talloc_sub_specified(NULL, lp_template, username, domname,
+ uid, gid);
if (!templ)
return False;
safe_strcpy(out, templ, sizeof(fstring) - 1);
- SAFE_FREE(templ);
+ TALLOC_FREE(templ);
return True;
@@ -81,14 +80,14 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
/* Resolve the uid number */
- if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid, 0))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) {
DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid)));
return False;
}
/* Resolve the gid number */
- if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid, 0))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) {
DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid)));
return False;
}
@@ -109,11 +108,6 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
defaults are /tmp for the home directory and /bin/false for
shell. */
- /* The substitution of %U and %D in the 'template homedir' is done
- by alloc_sub_specified() below. */
-
- fstrcpy(current_user_info.domain, dom_name);
-
if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name,
pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir))
return False;
@@ -162,6 +156,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain,
fstrcpy(state->response.data.user_info.full_name, user_info.full_name);
fstrcpy(state->response.data.user_info.homedir, user_info.homedir);
fstrcpy(state->response.data.user_info.shell, user_info.shell);
+ state->response.data.user_info.primary_gid = user_info.primary_gid;
if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid,
&state->response.data.user_info.group_rid)) {
DEBUG(1, ("Could not extract group rid out of %s\n",
@@ -190,6 +185,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
const char *full_name,
const char *homedir,
const char *shell,
+ uint32 gid,
uint32 group_rid);
static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid);
static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid);
@@ -228,6 +224,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
const char *full_name,
const char *homedir,
const char *shell,
+ uint32 gid,
uint32 group_rid)
{
fstring username;
@@ -244,9 +241,13 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
fstrcpy( username, acct_name );
strlower_m( username );
s->username = talloc_strdup(s->state->mem_ctx, username);
+
+ ws_name_replace( s->username, '_' );
+
s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
s->shell = talloc_strdup(s->state->mem_ctx, shell);
+ s->gid = gid;
sid_copy(&s->group_sid, &s->domain->sid);
sid_append_rid(&s->group_sid, group_rid);
@@ -278,13 +279,23 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
struct winbindd_pw *pw;
fstring output_username;
- if (!success) {
- DEBUG(5, ("Could not query user's %s\\%s\n gid",
- s->domain->name, s->username));
- goto failed;
- }
+ /* allow the nss backend to override the primary group ID.
+ If the gid has already been set, then keep it.
+ This makes me feel dirty. If the nss backend already
+ gave us a gid, we don't really care whether the sid2gid()
+ call worked or not. --jerry */
+
+ if ( s->gid == (gid_t)-1 ) {
- s->gid = gid;
+ if (!success) {
+ DEBUG(5, ("Could not query user's %s\\%s\n gid",
+ s->domain->name, s->username));
+ goto failed;
+ }
+
+ /* take what the sid2gid() call gave us */
+ s->gid = gid;
+ }
pw = &s->state->response.data.pw;
pw->pw_uid = s->uid;
@@ -293,8 +304,6 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1);
- fstrcpy(current_user_info.domain, s->domain->name);
-
if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name,
pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) {
DEBUG(5, ("Could not compose homedir\n"));
@@ -322,7 +331,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
/* Return a password structure from a username. */
static void getpwnam_name2sid_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type);
+ const DOM_SID *sid, enum lsa_SidType type);
void winbindd_getpwnam(struct winbindd_cli_state *state)
{
@@ -368,9 +377,10 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
}
static void getpwnam_name2sid_recv(void *private_data, BOOL success,
- const DOM_SID *sid, enum SID_NAME_USE type)
+ const DOM_SID *sid, enum lsa_SidType type)
{
- struct winbindd_cli_state *state = private_data;
+ struct winbindd_cli_state *state =
+ (struct winbindd_cli_state *)private_data;
if (!success) {
DEBUG(5, ("Could not lookup name for user %s\n",
@@ -390,7 +400,8 @@ static void getpwnam_name2sid_recv(void *private_data, BOOL success,
static void getpwuid_recv(void *private_data, BOOL success, const char *sid)
{
- struct winbindd_cli_state *state = private_data;
+ struct winbindd_cli_state *state =
+ (struct winbindd_cli_state *)private_data;
DOM_SID user_sid;
if (!success) {
@@ -410,30 +421,11 @@ static void getpwuid_recv(void *private_data, BOOL success, const char *sid)
/* Return a password structure given a uid number */
void winbindd_getpwuid(struct winbindd_cli_state *state)
{
- DOM_SID user_sid;
- NTSTATUS status;
-
- /* Bug out if the uid isn't in the winbind range */
- if ((state->request.data.uid < server_state.uid_low ) ||
- (state->request.data.uid > server_state.uid_high)) {
- request_error(state);
- return;
- }
-
DEBUG(3, ("[%5lu]: getpwuid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.uid));
- status = idmap_uid_to_sid(&user_sid, state->request.data.uid,
- ID_QUERY_ONLY | ID_CACHE_ONLY);
-
- if (NT_STATUS_IS_OK(status)) {
- winbindd_getpwsid(state, &user_sid);
- return;
- }
-
- DEBUG(10,("Could not find SID for uid %lu in the cache. Querying idmap backend\n",
- (unsigned long)state->request.data.uid));
-
+ /* always query idmap via the async interface */
+ /* if this turns to be too slow we will add here a direct query to the cache */
winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, getpwuid_recv, state);
}
@@ -542,7 +534,6 @@ static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx)
uint32 num_entries;
WINBIND_USERINFO *info;
struct getpwent_user *name_list = NULL;
- BOOL result = False;
struct winbindd_domain *domain;
struct winbindd_methods *methods;
unsigned int i;
@@ -570,12 +561,18 @@ static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx)
status = methods->query_user_list(domain, mem_ctx, &num_entries,
&info);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("get_sam_user_entries: query_user_list failed with %s\n",
+ nt_errstr(status) ));
+ return False;
+ }
+
if (num_entries) {
name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries);
if (!name_list) {
DEBUG(0,("get_sam_user_entries realloc failed.\n"));
- goto done;
+ return False;
}
}
@@ -620,11 +617,7 @@ static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx)
ent->sam_entries = name_list;
ent->sam_entry_index = 0;
- result = ent->num_sam_entries > 0;
-
- done:
-
- return result;
+ return ent->num_sam_entries > 0;
}
/* Fetch next passwd entry from ntdom database */
@@ -699,7 +692,7 @@ void winbindd_getpwent(struct winbindd_cli_state *state)
break;
}
- name_list = ent->sam_entries;
+ name_list = (struct getpwent_user *)ent->sam_entries;
/* Lookup user info */
@@ -775,13 +768,18 @@ void winbindd_list_users(struct winbindd_cli_state *state)
status = methods->query_user_list(domain, state->mem_ctx,
&num_entries, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ continue;
+ }
+
if (num_entries == 0)
continue;
/* Allocate some memory for extra data */
total_entries += num_entries;
- extra_data = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
+ extra_data = (char *)SMB_REALLOC(
+ extra_data, sizeof(fstring) * total_entries);
if (!extra_data) {
DEBUG(0,("failed to enlarge buffer!\n"));
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 5904ad0989a..72c85a9c6a4 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -27,6 +27,9 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+extern struct winbindd_methods cache_methods;
+extern struct winbindd_methods passdb_methods;
+
/**
* @file winbindd_util.c
*
@@ -163,6 +166,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
domain->last_seq_check = 0;
domain->initialized = False;
domain->online = is_internal_domain(sid);
+ domain->check_online_timeout = 0;
if (sid) {
sid_copy(&domain->sid, sid);
}
@@ -224,7 +228,6 @@ static void add_trusted_domains( struct winbindd_domain *domain )
static void trustdom_recv(void *private_data, BOOL success)
{
- extern struct winbindd_methods cache_methods;
struct trustdom_state *state =
talloc_get_type_abort(private_data, struct trustdom_state);
struct winbindd_response *response = state->response;
@@ -236,7 +239,7 @@ static void trustdom_recv(void *private_data, BOOL success)
return;
}
- p = response->extra_data.data;
+ p = (char *)response->extra_data.data;
while ((p != NULL) && (*p != '\0')) {
char *q, *sidstr, *alt_name;
@@ -265,8 +268,13 @@ static void trustdom_recv(void *private_data, BOOL success)
*q = '\0';
if (!string_to_sid(&sid, sidstr)) {
- DEBUG(0, ("Got invalid trustdom response\n"));
- break;
+ /* Allow NULL sid for sibling domains */
+ if ( strcmp(sidstr,"S-0-0") == 0) {
+ sid_copy( &sid, &global_sid_NULL);
+ } else {
+ DEBUG(0, ("Got invalid trustdom response\n"));
+ break;
+ }
}
if (find_domain_from_name_noinit(p) == NULL) {
@@ -350,6 +358,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
if ((request == NULL) || (response == NULL) || (state == NULL)) {
DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(mem_ctx);
continuation(private_data, False);
return WINBINDD_ERROR;
}
@@ -439,7 +448,7 @@ static void init_child_recv(void *private_data, BOOL success)
state->domain->sequence_number =
state->response->data.domain_info.sequence_number;
- state->domain->initialized = 1;
+ init_dc_connection(state->domain);
if (state->continuation != NULL)
state->continuation(state->private_data, True);
@@ -449,8 +458,6 @@ static void init_child_recv(void *private_data, BOOL success)
enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- struct in_addr ipaddr;
-
/* Ensure null termination */
state->request.domain_name
[sizeof(state->request.domain_name)-1]='\0';
@@ -461,24 +468,16 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai
fstrcpy(domain->dcname, state->request.data.init_conn.dcname);
}
- if (strlen(domain->dcname) > 0) {
- if (!resolve_name(domain->dcname, &ipaddr, 0x20)) {
- DEBUG(2, ("Could not resolve DC name %s for domain %s\n",
- domain->dcname, domain->name));
- return WINBINDD_ERROR;
- }
-
- domain->dcaddr.sin_family = PF_INET;
- putip((char *)&(domain->dcaddr.sin_addr), (char *)&ipaddr);
- domain->dcaddr.sin_port = 0;
- }
-
- set_dc_type_and_flags(domain);
+ init_dc_connection(domain);
if (!domain->initialized) {
- DEBUG(1, ("Could not initialize domain %s\n",
- state->request.domain_name));
- return WINBINDD_ERROR;
+ /* If we return error here we can't do any cached authentication,
+ but we may be in disconnected mode and can't initialize correctly.
+ Do what the previous code did and just return without initialization,
+ once we go online we'll re-initialize.
+ */
+ DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
+ "online = %d\n", domain->name, (int)domain->online ));
}
fstrcpy(state->response.data.domain_info.name, domain->name);
@@ -501,8 +500,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai
/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
- extern struct winbindd_methods cache_methods;
- extern struct winbindd_methods passdb_methods;
struct winbindd_domain *domain;
int role = lp_server_role();
@@ -523,6 +520,14 @@ BOOL init_domain_list(void)
&cache_methods, &our_sid);
domain->primary = True;
setup_domain_child(domain, &domain->child, NULL);
+
+ /* Even in the parent winbindd we'll need to
+ talk to the DC, so try and see if we can
+ contact it. Theoretically this isn't neccessary
+ as the init_dc_connection() in init_child_recv()
+ will do this, but we can start detecting the DC
+ early here. */
+ set_domain_online_request(domain);
}
/* Local SAM */
@@ -584,7 +589,7 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name)
return NULL;
if (!domain->initialized)
- set_dc_type_and_flags(domain);
+ init_dc_connection(domain);
return domain;
}
@@ -619,7 +624,7 @@ struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
return NULL;
if (!domain->initialized)
- set_dc_type_and_flags(domain);
+ init_dc_connection(domain);
return domain;
}
@@ -639,6 +644,19 @@ struct winbindd_domain *find_our_domain(void)
return NULL;
}
+struct winbindd_domain *find_root_domain(void)
+{
+ struct winbindd_domain *ours = find_our_domain();
+
+ if ( !ours )
+ return NULL;
+
+ if ( strlen(ours->forest_name) == 0 )
+ return NULL;
+
+ return find_domain_from_name( ours->forest_name );
+}
+
struct winbindd_domain *find_builtin_domain(void)
{
DOM_SID sid;
@@ -691,14 +709,14 @@ BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx,
struct winbindd_domain *domain,
const char *domain_name,
const char *name, DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
NTSTATUS result;
/* Lookup name */
result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
- /* Return rid and type if lookup successful */
+ /* Return sid and type if lookup successful */
if (!NT_STATUS_IS_OK(result)) {
*type = SID_NAME_UNKNOWN;
}
@@ -719,16 +737,16 @@ BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx,
**/
BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx,
DOM_SID *sid,
- fstring dom_name,
- fstring name,
- enum SID_NAME_USE *type)
+ char **dom_name,
+ char **name,
+ enum lsa_SidType *type)
{
- char *names;
- char *dom_names;
NTSTATUS result;
- BOOL rv = False;
struct winbindd_domain *domain;
+ *dom_name = NULL;
+ *name = NULL;
+
domain = find_lookup_domain_from_sid(sid);
if (!domain) {
@@ -738,19 +756,17 @@ BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx,
/* Lookup name */
- result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type);
+ result = domain->methods->sid_to_name(domain, mem_ctx, sid, dom_name, name, type);
/* Return name and type if successful */
- if ((rv = NT_STATUS_IS_OK(result))) {
- fstrcpy(dom_name, dom_names);
- fstrcpy(name, names);
- } else {
- *type = SID_NAME_UNKNOWN;
- fstrcpy(name, name_deadbeef);
+ if (NT_STATUS_IS_OK(result)) {
+ return True;
}
+
+ *type = SID_NAME_UNKNOWN;
- return rv;
+ return False;
}
/* Free state information held for {set,get,end}{pw,gr}ent() functions */
@@ -777,39 +793,6 @@ void free_getent_state(struct getent_state *state)
}
}
-/* Parse winbindd related parameters */
-
-BOOL winbindd_param_init(void)
-{
- /* Parse winbind uid and winbind_gid parameters */
-
- if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) {
- DEBUG(0, ("winbindd: idmap uid range missing or invalid\n"));
- DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
- return False;
- }
-
- if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) {
- DEBUG(0, ("winbindd: idmap gid range missing or invalid\n"));
- DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
- return False;
- }
-
- return True;
-}
-
-BOOL is_in_uid_range(uid_t uid)
-{
- return ((uid >= server_state.uid_low) &&
- (uid <= server_state.uid_high));
-}
-
-BOOL is_in_gid_range(gid_t gid)
-{
- return ((gid >= server_state.gid_low) &&
- (gid <= server_state.gid_high));
-}
-
/* Is this a domain which we may assume no DOMAIN\ prefix? */
static BOOL assume_domain(const char *domain)
@@ -875,6 +858,26 @@ BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
return ((*domain != NULL) && (*user != NULL));
}
+/* Ensure an incoming username from NSS is fully qualified. Replace the
+ incoming fstring with DOMAIN <separator> user. Returns the same
+ values as parse_domain_user() but also replaces the incoming username.
+ Used to ensure all names are fully qualified within winbindd.
+ Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
+ The protocol definitions of auth_crap, chng_pswd_auth_crap
+ really should be changed to use this instead of doing things
+ by hand. JRA. */
+
+BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user)
+{
+ if (!parse_domain_user(username_inout, domain, user)) {
+ return False;
+ }
+ slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
+ domain, *lp_winbind_separator(),
+ user);
+ return True;
+}
+
/*
Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
'winbind separator' options.
@@ -1015,209 +1018,6 @@ int winbindd_num_clients(void)
return _num_clients;
}
-/*****************************************************************************
- For idmap conversion: convert one record to new format
- Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid
- instead of the SID.
-*****************************************************************************/
-static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state)
-{
- struct winbindd_domain *domain;
- char *p;
- DOM_SID sid;
- uint32 rid;
- fstring keystr;
- fstring dom_name;
- TDB_DATA key2;
- BOOL *failed = (BOOL *)state;
-
- DEBUG(10,("Converting %s\n", key.dptr));
-
- p = strchr(key.dptr, '/');
- if (!p)
- return 0;
-
- *p = 0;
- fstrcpy(dom_name, key.dptr);
- *p++ = '/';
-
- domain = find_domain_from_name(dom_name);
- if (domain == NULL) {
- /* We must delete the old record. */
- DEBUG(0,("Unable to find domain %s\n", dom_name ));
- DEBUG(0,("deleting record %s\n", key.dptr ));
-
- if (tdb_delete(tdb, key) != 0) {
- DEBUG(0, ("Unable to delete record %s\n", key.dptr));
- *failed = True;
- return -1;
- }
-
- return 0;
- }
-
- rid = atoi(p);
-
- sid_copy(&sid, &domain->sid);
- sid_append_rid(&sid, rid);
-
- sid_to_string(keystr, &sid);
- key2.dptr = keystr;
- key2.dsize = strlen(keystr) + 1;
-
- if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) {
- DEBUG(0,("Unable to add record %s\n", key2.dptr ));
- *failed = True;
- return -1;
- }
-
- if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) {
- DEBUG(0,("Unable to update record %s\n", data.dptr ));
- *failed = True;
- return -1;
- }
-
- if (tdb_delete(tdb, key) != 0) {
- DEBUG(0,("Unable to delete record %s\n", key.dptr ));
- *failed = True;
- return -1;
- }
-
- return 0;
-}
-
-/* These definitions are from sam/idmap_tdb.c. Replicated here just
- out of laziness.... :-( */
-
-/* High water mark keys */
-#define HWM_GROUP "GROUP HWM"
-#define HWM_USER "USER HWM"
-
-/*****************************************************************************
- Convert the idmap database from an older version.
-*****************************************************************************/
-
-static BOOL idmap_convert(const char *idmap_name)
-{
- int32 vers;
- BOOL bigendianheader;
- BOOL failed = False;
- TDB_CONTEXT *idmap_tdb;
-
- if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
- TDB_DEFAULT, O_RDWR,
- 0600))) {
- DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
- return False;
- }
-
- bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
-
- vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
-
- if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
- /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
- /*
- * high and low records were created on a
- * big endian machine and will need byte-reversing.
- */
-
- int32 wm;
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
-
- if (wm != -1) {
- wm = IREV(wm);
- } else {
- wm = server_state.uid_low;
- }
-
- if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
- DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
- if (wm != -1) {
- wm = IREV(wm);
- } else {
- wm = server_state.gid_low;
- }
-
- if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
- DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
- tdb_close(idmap_tdb);
- return False;
- }
- }
-
- /* the old format stored as DOMAIN/rid - now we store the SID direct */
- tdb_traverse(idmap_tdb, convert_fn, &failed);
-
- if (failed) {
- DEBUG(0, ("Problem during conversion\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
- DEBUG(0, ("idmap_convert: Unable to dtore idmap version in databse\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- tdb_close(idmap_tdb);
- return True;
-}
-
-/*****************************************************************************
- Convert the idmap database from an older version if necessary
-*****************************************************************************/
-
-BOOL winbindd_upgrade_idmap(void)
-{
- pstring idmap_name;
- pstring backup_name;
- SMB_STRUCT_STAT stbuf;
- TDB_CONTEXT *idmap_tdb;
-
- pstrcpy(idmap_name, lock_path("winbindd_idmap.tdb"));
-
- if (!file_exist(idmap_name, &stbuf)) {
- /* nothing to convert return */
- return True;
- }
-
- if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
- TDB_DEFAULT, O_RDWR,
- 0600))) {
- DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
- return False;
- }
-
- if (tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) {
- /* nothing to convert return */
- tdb_close(idmap_tdb);
- return True;
- }
-
- /* backup_tdb expects the tdb not to be open */
- tdb_close(idmap_tdb);
-
- DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n"));
-
- pstrcpy(backup_name, idmap_name);
- pstrcat(backup_name, ".bak");
-
- if (backup_tdb(idmap_name, backup_name) != 0) {
- DEBUG(0, ("Could not backup idmap database\n"));
- return False;
- }
-
- return idmap_convert(idmap_name);
-}
-
NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *user_sid,
@@ -1249,14 +1049,20 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
/* always add the primary group to the sid array */
sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
- add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups);
+ if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
+ SAFE_FREE(info3);
+ return NT_STATUS_NO_MEMORY;
+ }
for (i=0; i<info3->num_groups; i++) {
sid_copy(&group_sid, &info3->dom_sid.sid);
sid_append_rid(&group_sid, info3->gids[i].g_rid);
- add_sid_to_array(mem_ctx, &group_sid, user_sids,
- &num_groups);
+ if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
+ &num_groups)) {
+ SAFE_FREE(info3);
+ return NT_STATUS_NO_MEMORY;
+ }
}
SAFE_FREE(info3);
@@ -1267,3 +1073,37 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
return status;
}
+
+/*********************************************************************
+ We use this to remove spaces from user and group names
+********************************************************************/
+
+void ws_name_replace( char *name, char replace )
+{
+ char replace_char[2] = { 0x0, 0x0 };
+
+ if ( !lp_winbind_normalize_names() || (replace == '\0') )
+ return;
+
+ replace_char[0] = replace;
+ all_string_sub( name, " ", replace_char, 0 );
+
+ return;
+}
+
+/*********************************************************************
+ We use this to do the inverse of ws_name_replace()
+********************************************************************/
+
+void ws_name_return( char *name, char replace )
+{
+ char replace_char[2] = { 0x0, 0x0 };
+
+ if ( !lp_winbind_normalize_names() || (replace == '\0') )
+ return;
+
+ replace_char[0] = replace;
+ all_string_sub( name, replace_char, " ", 0 );
+
+ return;
+}
diff --git a/source/nsswitch/winbindd_wins.c b/source/nsswitch/winbindd_wins.c
index 2cb835b3733..844099aabda 100644
--- a/source/nsswitch/winbindd_wins.c
+++ b/source/nsswitch/winbindd_wins.c
@@ -95,7 +95,7 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
/* always try with wins first */
if (resolve_wins(name,0x20,&ret,count)) {
- if ( count == 0 )
+ if ( *count == 0 )
return NULL;
if ( (return_ip = SMB_MALLOC_ARRAY(struct in_addr, *count)) == NULL ) {
free( ret );
diff --git a/source/nsswitch/wins.c b/source/nsswitch/wins.c
index 2cc7edb4c7b..697bc15f97a 100644
--- a/source/nsswitch/wins.c
+++ b/source/nsswitch/wins.c
@@ -34,6 +34,11 @@ static int initialised;
extern BOOL AllowDebugChange;
+NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
+ char *buffer, size_t buflen, int *h_errnop);
+NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he,
+ char *buffer, size_t buflen, int *h_errnop);
+
/* Use our own create socket code so we don't recurse.... */
static int wins_lookup_open_socket_in(void)
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index b6c027f8714..5d6a0c4ff54 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -58,6 +58,7 @@ BOOL bLoaded = False;
extern pstring user_socket_options;
extern enum protocol_types Protocol;
+extern userdom_struct current_user_info;
#ifndef GLOBAL_NAME
#define GLOBAL_NAME "global"
@@ -179,7 +180,10 @@ typedef struct {
BOOL bWinbindNestedGroups;
BOOL bWinbindRefreshTickets;
BOOL bWinbindOfflineLogon;
- char **szIdmapBackend;
+ BOOL bWinbindNormalizeNames;
+ char **szIdmapDomains;
+ char **szIdmapBackend; /* deprecated */
+ char *szIdmapAllocBackend;
char *szAddShareCommand;
char *szChangeShareCommand;
char *szDeleteShareCommand;
@@ -295,8 +299,6 @@ typedef struct {
BOOL bHostnameLookups;
BOOL bUnixExtensions;
BOOL bDisableNetbios;
- BOOL bKernelChangeNotify;
- BOOL bFamChangeNotify;
BOOL bUseKerberosKeytab;
BOOL bDeferSharingViolations;
BOOL bEnablePrivileges;
@@ -308,6 +310,8 @@ typedef struct {
int client_signing;
int server_signing;
int iUsershareMaxShares;
+ int iIdmapExpireTime;
+ int iIdmapNegativeTime;
BOOL bResetOnZeroVC;
param_opt_struct *param_opt;
@@ -344,6 +348,7 @@ typedef struct {
char *szQueuepausecommand;
char *szQueueresumecommand;
char *szPrintername;
+ char *szPrintjobUsername;
char *szDontdescend;
char **szHostsallow;
char **szHostsdeny;
@@ -445,11 +450,12 @@ typedef struct {
BOOL bAclCheckPermissions;
BOOL bAclMapFullControl;
BOOL bAclGroupControl;
+ BOOL bChangeNotify;
+ BOOL bKernelChangeNotify;
int iallocation_roundup_size;
int iAioReadSize;
int iAioWriteSize;
int iMap_readonly;
- int ichange_notify_timeout;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -483,6 +489,7 @@ static service sDefault = {
NULL, /* szQueuepausecommand */
NULL, /* szQueueresumecommand */
NULL, /* szPrintername */
+ NULL, /* szPrintjobUsername */
NULL, /* szDontdescend */
NULL, /* szHostsallow */
NULL, /* szHostsdeny */
@@ -570,7 +577,7 @@ static service sDefault = {
False, /* bInheritPerms */
False, /* bInheritACLS */
False, /* bInheritOwner */
- True, /* bMSDfsRoot */
+ False, /* bMSDfsRoot */
False, /* bUseClientDriver */
True, /* bDefaultDevmode */
False, /* bForcePrintername */
@@ -584,11 +591,12 @@ static service sDefault = {
True, /* bAclCheckPermissions */
True, /* bAclMapFullControl */
False, /* bAclGroupControl */
+ True, /* bChangeNotify */
+ True, /* bKernelChangeNotify */
SMB_ROUNDUP_ALLOCATION_SIZE, /* iallocation_roundup_size */
0, /* iAioReadSize */
0, /* iAioWriteSize */
MAP_READONLY_YES, /* iMap_readonly */
- 60, /* ichange_notify_timeout = 1 minute default. */
NULL, /* Parametric options */
@@ -999,12 +1007,11 @@ static struct parm_struct parm_table[] = {
{N_("Tuning Options"), P_SEP, P_SEPARATOR},
{"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
- {"change notify timeout", P_INTEGER, P_LOCAL, &sDefault.ichange_notify_timeout, NULL, NULL, FLAG_ADVANCED},
{"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED},
{"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED},
{"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED},
- {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED},
- {"fam change notify", P_BOOL, P_GLOBAL, &Globals.bFamChangeNotify, NULL, NULL, FLAG_ADVANCED},
+ {"change notify", P_BOOL, P_LOCAL, &sDefault.bChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
+ {"kernel change notify", P_BOOL, P_LOCAL, &sDefault.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
{"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED},
{"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED},
@@ -1062,6 +1069,7 @@ static struct parm_struct parm_table[] = {
{"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
{"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
{"force printername", P_BOOL, P_LOCAL, &sDefault.bForcePrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
+ {"printjob username", P_STRING, P_LOCAL, &sDefault.szPrintjobUsername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
{N_("Filename Handling"), P_SEP, P_SEPARATOR},
{"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED},
@@ -1260,11 +1268,15 @@ static struct parm_struct parm_table[] = {
{N_("Winbind options"), P_SEP, P_SEPARATOR},
{"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
- {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED},
- {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
- {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE},
- {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED},
- {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE},
+ {"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED},
+ {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
+ {"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED},
+ {"idmap expire time", P_INTEGER, P_GLOBAL, &Globals.iIdmapExpireTime, NULL, NULL, FLAG_ADVANCED},
+ {"idmap negative time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeTime, NULL, NULL, FLAG_ADVANCED},
+ {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
+ {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE | FLAG_DEPRECATED },
+ {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
+ {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE | FLAG_DEPRECATED },
{"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED},
{"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED},
{"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED},
@@ -1277,6 +1289,7 @@ static struct parm_struct parm_table[] = {
{"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED},
{"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED},
{"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
+ {"winbind normalize names", P_BOOL, P_GLOBAL, &Globals.bWinbindNormalizeNames, NULL, NULL, FLAG_ADVANCED},
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
};
@@ -1400,6 +1413,7 @@ static void init_globals(BOOL first_time_only)
string_set((char **)parm_table[i].ptr, "");
string_set(&sDefault.fstype, FSTYPE_STRING);
+ string_set(&sDefault.szPrintjobUsername, "%U");
init_printer_values(&sDefault);
@@ -1511,8 +1525,6 @@ static void init_globals(BOOL first_time_only)
Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
- Globals.bKernelChangeNotify = True; /* On if we have it. */
- Globals.bFamChangeNotify = True; /* On if we have it. */
Globals.lm_announce = 2; /* = Auto: send only if LM clients found */
Globals.lm_interval = 60;
Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
@@ -1533,7 +1545,7 @@ static void init_globals(BOOL first_time_only)
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.iMaxStatCacheSize = 1024; /* one Meg 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 */
@@ -1545,8 +1557,8 @@ static void init_globals(BOOL first_time_only)
Globals.map_to_guest = 0; /* By Default, "Never" */
Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
Globals.enhanced_browsing = True;
- Globals.iLockSpinCount = 3; /* Try 3 times. */
- Globals.iLockSpinTime = 10; /* usec. */
+ Globals.iLockSpinCount = 0; /* Unused. */
+ Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
#ifdef MMAP_BLACKLIST
Globals.bUseMmap = False;
#else
@@ -1611,6 +1623,7 @@ static void init_globals(BOOL first_time_only)
string_set(&Globals.szTemplateShell, "/bin/false");
string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
string_set(&Globals.szWinbindSeparator, "\\");
+
string_set(&Globals.szCupsServer, "");
string_set(&Globals.szIPrintServer, "");
@@ -1624,6 +1637,9 @@ static void init_globals(BOOL first_time_only)
Globals.bWinbindRefreshTickets = False;
Globals.bWinbindOfflineLogon = False;
+ Globals.iIdmapExpireTime = 900; /* 15 minutes by default */
+ Globals.iIdmapNegativeTime = 120; /* 2 minutes by default */
+
Globals.bPassdbExpandExplicit = False;
Globals.name_cache_timeout = 660; /* In seconds */
@@ -1702,11 +1718,13 @@ static char *lp_string(const char *s)
if (!lp_talloc)
lp_talloc = talloc_init("lp_talloc");
- tmpstr = alloc_sub_basic(get_current_username(), s);
+ tmpstr = alloc_sub_basic(get_current_username(),
+ current_user_info.domain, s);
if (trim_char(tmpstr, '\"', '\"')) {
if (strchr(tmpstr,'\"') != NULL) {
SAFE_FREE(tmpstr);
- tmpstr = alloc_sub_basic(get_current_username(),s);
+ tmpstr = alloc_sub_basic(get_current_username(),
+ current_user_info.domain, s);
}
}
ret = talloc_strdup(lp_talloc, tmpstr);
@@ -1741,11 +1759,18 @@ static char *lp_string(const char *s)
const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
#define FN_LOCAL_BOOL(fn_name,val) \
BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
-#define FN_LOCAL_CHAR(fn_name,val) \
- char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
#define FN_LOCAL_INTEGER(fn_name,val) \
int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
+#define FN_LOCAL_PARM_BOOL(fn_name,val) \
+ BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
+#define FN_LOCAL_PARM_INTEGER(fn_name,val) \
+ int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
+#define FN_LOCAL_PARM_STRING(fn_name,val) \
+ char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
+#define FN_LOCAL_CHAR(fn_name,val) \
+ char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
+
FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
@@ -1795,7 +1820,48 @@ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
-FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
+/* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
+ * lp_passdb_backend() should be replace by the this macro again after
+ * some releases.
+ * */
+const char *lp_passdb_backend(void)
+{
+ char *delim, *quote;
+
+ delim = strchr( Globals.szPassdbBackend, ' ');
+ /* no space at all */
+ if (delim == NULL) {
+ goto out;
+ }
+
+ quote = strchr(Globals.szPassdbBackend, '"');
+ /* no quote char or non in the first part */
+ if (quote == NULL || quote > delim) {
+ *delim = '\0';
+ goto warn;
+ }
+
+ quote = strchr(quote+1, '"');
+ if (quote == NULL) {
+ DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
+ goto out;
+ } else if (*(quote+1) == '\0') {
+ /* space, fitting quote char, and one backend only */
+ goto out;
+ } else {
+ /* terminate string after the fitting quote char */
+ *(quote+1) = '\0';
+ }
+
+warn:
+ DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends. This\n"
+ "is deprecated since Samba 3.0.23. Please check WHATSNEW.txt or the section 'Passdb\n"
+ "Changes' from the ChangeNotes as part of the Samba HOWTO collection. Only the first\n"
+ "backend (%s) is used. The rest is ignored.\n", Globals.szPassdbBackend));
+
+out:
+ return Globals.szPassdbBackend;
+}
FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
@@ -1829,8 +1895,13 @@ FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsO
FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
+FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
-FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
+FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
+FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
+FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
+FN_GLOBAL_INTEGER(lp_idmap_expire_time, &Globals.iIdmapExpireTime)
+FN_GLOBAL_INTEGER(lp_idmap_negative_time, &Globals.iIdmapNegativeTime)
FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
@@ -1905,8 +1976,8 @@ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
-FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
-FN_GLOBAL_BOOL(lp_fam_change_notify, &Globals.bFamChangeNotify)
+FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
+FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
@@ -1940,7 +2011,7 @@ FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout
FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
-FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
+FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
FN_LOCAL_STRING(lp_preexec, szPreExec)
@@ -1967,6 +2038,7 @@ FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
static FN_LOCAL_STRING(_lp_printername, szPrintername)
+FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
FN_LOCAL_STRING(lp_magicscript, szMagicScript)
@@ -1981,7 +2053,7 @@ FN_LOCAL_STRING(lp_fstype, fstype)
FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
static FN_LOCAL_STRING(lp_volume, volume)
-FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
+FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
FN_LOCAL_STRING(lp_hide_files, szHideFiles)
FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
@@ -2008,14 +2080,14 @@ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
-FN_LOCAL_BOOL(lp_locking, bLocking)
-FN_LOCAL_INTEGER(lp_strict_locking, iStrictLocking)
-FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
+FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
+FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
+FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
FN_LOCAL_BOOL(lp_share_modes, bShareModes)
FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
-FN_LOCAL_BOOL(lp_manglednames, bMangledNames)
+FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
@@ -2068,7 +2140,6 @@ FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
-FN_LOCAL_INTEGER(lp_change_notify_timeout, ichange_notify_timeout)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
@@ -2224,6 +2295,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
* lp_parm_string is only used to let old modules find this symbol
*/
#undef lp_parm_string
+ char *lp_parm_string(const char *servicename, const char *type, const char *option);
char *lp_parm_string(const char *servicename, const char *type, const char *option)
{
return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
@@ -3002,7 +3074,9 @@ BOOL lp_file_list_changed(void)
time_t mod_time;
pstrcpy(n2, f->name);
- standard_sub_basic( get_current_username(), n2, sizeof(n2) );
+ standard_sub_basic( get_current_username(),
+ current_user_info.domain,
+ n2, sizeof(n2) );
DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
f->name, n2, ctime(&f->modtime)));
@@ -3036,7 +3110,8 @@ static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
pstrcpy(netbios_name, pszParmValue);
- standard_sub_basic(get_current_username(), netbios_name,sizeof(netbios_name));
+ standard_sub_basic(get_current_username(), current_user_info.domain,
+ netbios_name, sizeof(netbios_name));
ret = set_global_myname(netbios_name);
string_set(&Globals.szNetbiosName,global_myname());
@@ -3094,7 +3169,8 @@ static BOOL handle_include(int snum, const char *pszParmValue, char **ptr)
pstring fname;
pstrcpy(fname, pszParmValue);
- standard_sub_basic(get_current_username(), fname,sizeof(fname));
+ standard_sub_basic(get_current_username(), current_user_info.domain,
+ fname,sizeof(fname));
add_to_file_list(pszParmValue, fname);
@@ -3852,7 +3928,6 @@ static void dump_a_service(service * pService, FILE * f)
BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
{
- service * pService = ServicePtrs[snum];
int i;
BOOL result = False;
parm_class p_class;
@@ -3895,11 +3970,13 @@ BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
{
void *ptr;
- if (isGlobal)
+ if (isGlobal) {
ptr = parm_table[i].ptr;
- else
+ } else {
+ service * pService = ServicePtrs[snum];
ptr = ((char *)pService) +
PTR_DIFF(parm_table[i].ptr, &sDefault);
+ }
print_parameter(&parm_table[i],
ptr, f);
@@ -4187,7 +4264,8 @@ static void set_server_role(void)
case SEC_SERVER:
if (lp_domain_logons())
DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
- server_role = ROLE_DOMAIN_MEMBER;
+ /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
+ server_role = ROLE_STANDALONE;
break;
case SEC_DOMAIN:
if (lp_domain_logons()) {
@@ -4555,7 +4633,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
/* Should we allow printers to be shared... ? */
ctx = talloc_init("usershare_sd_xctx");
if (!ctx) {
- SAFE_FREE(lines);
+ file_lines_free(lines);
return 1;
}
@@ -4563,11 +4641,11 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
iService, lines, numlines, sharepath,
comment, &psd, &guest_ok) != USERSHARE_OK) {
talloc_destroy(ctx);
- SAFE_FREE(lines);
+ file_lines_free(lines);
return -1;
}
- SAFE_FREE(lines);
+ file_lines_free(lines);
/* Everything ok - add the service possibly using a template. */
if (iService < 0) {
@@ -4588,7 +4666,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
}
/* Write the ACL of the new/modified share. */
- if (!set_share_security(ctx, service_name, psd)) {
+ if (!set_share_security(service_name, psd)) {
DEBUG(0, ("process_usershare_file: Failed to set share "
"security for user share %s\n",
service_name ));
@@ -4861,7 +4939,7 @@ int load_usershare_shares(void)
/* Remove from the share ACL db. */
DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
lp_servicename(iService) ));
- delete_share_security(iService);
+ delete_share_security(snum2params_static(iService));
free_service_byindex(iService);
}
}
@@ -4936,7 +5014,8 @@ BOOL lp_load(const char *pszFname,
pstrcpy(n2, pszFname);
- standard_sub_basic( get_current_username(), n2,sizeof(n2) );
+ standard_sub_basic( get_current_username(), current_user_info.domain,
+ n2,sizeof(n2) );
add_to_file_list(pszFname, n2);
@@ -5080,7 +5159,9 @@ int lp_servicenumber(const char *pszServiceName)
* service names
*/
fstrcpy(serviceName, ServicePtrs[iService]->szService);
- standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
+ standard_sub_basic(get_current_username(),
+ current_user_info.domain,
+ serviceName,sizeof(serviceName));
if (strequal(serviceName, pszServiceName)) {
break;
}
@@ -5092,7 +5173,7 @@ int lp_servicenumber(const char *pszServiceName)
if (!usershare_exists(iService, &last_mod)) {
/* Remove the share security tdb entry for it. */
- delete_share_security(iService);
+ delete_share_security(snum2params_static(iService));
/* Remove it from the array. */
free_service_byindex(iService);
/* Doesn't exist anymore. */
@@ -5116,6 +5197,98 @@ int lp_servicenumber(const char *pszServiceName)
return (iService);
}
+BOOL share_defined(const char *service_name)
+{
+ return (lp_servicenumber(service_name) != -1);
+}
+
+struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
+ const char *sharename)
+{
+ struct share_params *result;
+ char *sname;
+ int snum;
+
+ if (!(sname = SMB_STRDUP(sharename))) {
+ return NULL;
+ }
+
+ snum = find_service(sname);
+ SAFE_FREE(sname);
+
+ if (snum < 0) {
+ return NULL;
+ }
+
+ if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ result->service = snum;
+ return result;
+}
+
+struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
+{
+ struct share_iterator *result;
+
+ if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ result->next_id = 0;
+ return result;
+}
+
+struct share_params *next_share(struct share_iterator *list)
+{
+ struct share_params *result;
+
+ while (!lp_snum_ok(list->next_id) &&
+ (list->next_id < lp_numservices())) {
+ list->next_id += 1;
+ }
+
+ if (list->next_id >= lp_numservices()) {
+ return NULL;
+ }
+
+ if (!(result = TALLOC_P(list, struct share_params))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ result->service = list->next_id;
+ list->next_id += 1;
+ return result;
+}
+
+struct share_params *next_printer(struct share_iterator *list)
+{
+ struct share_params *result;
+
+ while ((result = next_share(list)) != NULL) {
+ if (lp_print_ok(result->service)) {
+ break;
+ }
+ }
+ return result;
+}
+
+/*
+ * This is a hack for a transition period until we transformed all code from
+ * service numbers to struct share_params.
+ */
+
+struct share_params *snum2params_static(int snum)
+{
+ static struct share_params result;
+ result.service = snum;
+ return &result;
+}
+
/*******************************************************************
A useful volume label function.
********************************************************************/
@@ -5453,17 +5626,23 @@ void lp_set_posix_pathnames(void)
Global state for POSIX lock processing - CIFS unix extensions.
********************************************************************/
+BOOL posix_default_lock_was_set;
static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
-enum brl_flavour lp_posix_cifsu_locktype(void)
+enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
{
- return posix_cifsx_locktype;
+ if (posix_default_lock_was_set) {
+ return posix_cifsx_locktype;
+ } else {
+ return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
+ }
}
/*******************************************************************
********************************************************************/
-void lp_set_posix_cifsx_locktype(enum brl_flavour val)
+void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
{
+ posix_default_lock_was_set = True;
posix_cifsx_locktype = val;
}
diff --git a/source/param/params.c b/source/param/params.c
index 6d036e40f69..c4ca5bb906b 100644
--- a/source/param/params.c
+++ b/source/param/params.c
@@ -587,7 +587,6 @@ BOOL pm_process( const char *FileName,
result = Parse( InFile, sfunc, pfunc );
SAFE_FREE( bufr );
- bufr = NULL;
bSize = 0;
}
diff --git a/source/passdb/login_cache.c b/source/passdb/login_cache.c
index 9a19dcf437a..7fd3b47826f 100644
--- a/source/passdb/login_cache.c
+++ b/source/passdb/login_cache.c
@@ -140,7 +140,7 @@ BOOL login_cache_write(const struct samu *sampass, LOGIN_CACHE entry)
entry.acct_ctrl,
entry.bad_password_count,
entry.bad_password_time);
- databuf.dptr = SMB_MALLOC(databuf.dsize);
+ databuf.dptr = SMB_MALLOC_ARRAY(char, databuf.dsize);
if (!databuf.dptr) {
SAFE_FREE(keybuf.dptr);
return False;
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index 7082cd3abd4..0b596fc8d7f 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -33,7 +33,7 @@
BOOL lookup_name(TALLOC_CTX *mem_ctx,
const char *full_name, int flags,
const char **ret_domain, const char **ret_name,
- DOM_SID *ret_sid, enum SID_NAME_USE *ret_type)
+ DOM_SID *ret_sid, enum lsa_SidType *ret_type)
{
char *p;
const char *tmp;
@@ -41,7 +41,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
const char *name = NULL;
uint32 rid;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
@@ -65,6 +65,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
if ((domain == NULL) || (name == NULL)) {
DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(tmp_ctx);
return False;
}
@@ -76,7 +77,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
sid_append_rid(&sid, rid);
goto ok;
}
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
if (strequal(domain, builtin_domain_name())) {
@@ -88,7 +90,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
type = SID_NAME_ALIAS;
goto ok;
}
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
/* Try the explicit winbind lookup first, don't let it guess the
@@ -104,7 +107,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
type = SID_NAME_USER;
goto ok;
}
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
if (strequal(domain, unix_groups_domain_name())) {
@@ -112,11 +116,13 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
type = SID_NAME_DOM_GRP;
goto ok;
}
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
/* Now the guesswork begins, we haven't been given an explicit
@@ -146,7 +152,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
if (strequal(name, get_global_sam_name())) {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch my SID\n"));
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
/* Swap domain and name */
tmp = name; name = domain; domain = tmp;
@@ -159,7 +166,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
if (!IS_DC && strequal(name, lp_workgroup())) {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch the domain SID\n"));
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
/* Swap domain and name */
tmp = name; name = domain; domain = tmp;
@@ -203,7 +211,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
/* Now our local possibilities are exhausted. */
if (!(flags & LOOKUP_NAME_REMOTE)) {
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
/* If we are not a DC, we have to ask in our primary domain. Let
@@ -223,7 +232,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
DOM_SID dom_sid;
uint32 tmp_rid;
- enum SID_NAME_USE domain_type;
+ enum lsa_SidType domain_type;
if (type == SID_NAME_DOMAIN) {
/* Swap name and type */
@@ -243,7 +252,8 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
(domain_type != SID_NAME_DOMAIN)) {
DEBUG(2, ("winbind could not find the domain's name "
"it just looked up for us\n"));
- goto failed;
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
goto ok;
}
@@ -265,7 +275,10 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
goto ok;
}
- failed:
+ /*
+ * Ok, all possibilities tried. Fail.
+ */
+
TALLOC_FREE(tmp_ctx);
return False;
@@ -276,14 +289,26 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
return False;
}
- if (ret_name != NULL) {
- *ret_name = talloc_steal(mem_ctx, name);
+ /*
+ * Hand over the results to the talloc context we've been given.
+ */
+
+ if ((ret_name != NULL) &&
+ !(*ret_name = talloc_strdup(mem_ctx, name))) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ return False;
}
if (ret_domain != NULL) {
- char *tmp_dom = talloc_strdup(tmp_ctx, domain);
+ char *tmp_dom;
+ if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ return False;
+ }
strupper_m(tmp_dom);
- *ret_domain = talloc_steal(mem_ctx, tmp_dom);
+ *ret_domain = tmp_dom;
}
if (ret_sid != NULL) {
@@ -307,7 +332,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
const char *full_name, int flags,
const char **ret_domain, const char **ret_name,
- DOM_SID *ret_sid, enum SID_NAME_USE *ret_type)
+ DOM_SID *ret_sid, enum lsa_SidType *ret_type)
{
char *qualified_name;
const char *p;
@@ -348,7 +373,7 @@ BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
ret_sid, ret_type)) {
return True;
}
-
+
/* Finally try with "Unix Users" or "Unix Group" */
qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
flags & LOOKUP_NAME_GROUP ?
@@ -364,46 +389,60 @@ BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
ret_sid, ret_type);
}
-static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
- const DOM_SID *domain_sid,
- int num_rids, uint32 *rids,
- const char **domain_name,
- const char **names, uint32 *types)
+static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char **names, enum lsa_SidType *types)
{
- /* Unless the winbind interface is upgraded, fall back to ask for
- * individual sids. I imagine introducing a lookuprids operation that
- * directly proxies to lsa_lookupsids to the correct DC. -- vl */
-
int i;
- for (i=0; i<num_rids; i++) {
- DOM_SID sid;
+ const char **my_names;
+ enum lsa_SidType *my_types;
+ TALLOC_CTX *tmp_ctx;
- sid_copy(&sid, domain_sid);
- sid_append_rid(&sid, rids[i]);
+ if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
+ return False;
+ }
- if (winbind_lookup_sid(mem_ctx, &sid,
- *domain_name == NULL ?
- domain_name : NULL,
- &names[i], &types[i])) {
- if ((names[i] == NULL) || ((*domain_name) == NULL)) {
- return False;
- }
- } else {
+ if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
+ domain_name, &my_names, &my_types)) {
+ *domain_name = "";
+ for (i=0; i<num_rids; i++) {
+ names[i] = "";
types[i] = SID_NAME_UNKNOWN;
}
+ return True;
+ }
+
+ /*
+ * winbind_lookup_rids allocates its own array. We've been given the
+ * array, so copy it over
+ */
+
+ for (i=0; i<num_rids; i++) {
+ if (my_names[i] == NULL) {
+ TALLOC_FREE(tmp_ctx);
+ return False;
+ }
+ if (!(names[i] = talloc_strdup(names, my_names[i]))) {
+ TALLOC_FREE(tmp_ctx);
+ return False;
+ }
+ types[i] = my_types[i];
}
+ TALLOC_FREE(tmp_ctx);
return True;
}
static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
int num_rids, uint32_t *rids,
const char **domain_name,
- const char ***names, enum SID_NAME_USE **types)
+ const char ***names, enum lsa_SidType **types)
{
int i;
*names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
- *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
if ((*names == NULL) || (*types == NULL)) {
return False;
@@ -500,8 +539,8 @@ static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
return True;
}
- return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
- domain_name, *names, *types);
+ return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
+ domain_name, *names, *types);
}
/*
@@ -512,7 +551,7 @@ static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
const char **name)
{
const char *tmp;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (sid_check_is_domain(sid)) {
*name = talloc_strdup(mem_ctx, get_global_sam_name());
@@ -638,18 +677,17 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
int i, j;
- tmp_ctx = talloc_new(mem_ctx);
- if (tmp_ctx == NULL) {
+ if (!(tmp_ctx = talloc_new(mem_ctx))) {
DEBUG(0, ("talloc_new failed\n"));
return NT_STATUS_NO_MEMORY;
}
- name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
- dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
+ name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
+ dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
MAX_REF_DOMAINS);
if ((name_infos == NULL) || (dom_infos == NULL)) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
/* First build up the data structures:
@@ -684,7 +722,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
*/
if (domain_name == NULL) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
name_infos[i].rid = 0;
@@ -698,14 +736,14 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
name_infos, builtin_domain_name());
if (name_infos[i].name == NULL) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
}
} else {
/* This is a normal SID with rid component */
if (!sid_split_rid(&sid, &rid)) {
result = NT_STATUS_INVALID_PARAMETER;
- goto done;
+ goto fail;
}
}
@@ -728,7 +766,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
if (j == MAX_REF_DOMAINS) {
/* TODO: What's the right error message here? */
result = NT_STATUS_NONE_MAPPED;
- goto done;
+ goto fail;
}
if (!dom_infos[j].valid) {
@@ -741,7 +779,11 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
/* This name was being found above in the case
* when we found a domain SID */
dom_infos[j].name =
- talloc_steal(dom_infos, domain_name);
+ talloc_strdup(dom_infos, domain_name);
+ if (dom_infos[j].name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
} else {
/* lookup_rids will take care of this */
dom_infos[j].name = NULL;
@@ -758,7 +800,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
if (dom_infos[j].idxs == NULL) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
}
}
@@ -767,8 +809,9 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
for (i=0; i<MAX_REF_DOMAINS; i++) {
uint32_t *rids;
+ const char *domain_name = NULL;
const char **names;
- enum SID_NAME_USE *types;
+ enum lsa_SidType *types;
struct lsa_dom_info *dom = &dom_infos[i];
if (!dom->valid) {
@@ -776,11 +819,9 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
break;
}
- rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
-
- if (rids == NULL) {
+ if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
for (j=0; j<dom->num_idxs; j++) {
@@ -788,31 +829,40 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
}
if (!lookup_rids(tmp_ctx, &dom->sid,
- dom->num_idxs, rids, &dom->name,
+ dom->num_idxs, rids, &domain_name,
&names, &types)) {
result = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
- talloc_steal(dom_infos, dom->name);
-
+ if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
+ result = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
for (j=0; j<dom->num_idxs; j++) {
int idx = dom->idxs[j];
name_infos[idx].type = types[j];
if (types[j] != SID_NAME_UNKNOWN) {
name_infos[idx].name =
- talloc_steal(name_infos, names[j]);
+ talloc_strdup(name_infos, names[j]);
+ if (name_infos[idx].name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
} else {
name_infos[idx].name = NULL;
}
}
}
- *ret_domains = talloc_steal(mem_ctx, dom_infos);
- *ret_names = talloc_steal(mem_ctx, name_infos);
- result = NT_STATUS_OK;
+ *ret_domains = dom_infos;
+ *ret_names = name_infos;
+ return NT_STATUS_OK;
- done:
+ fail:
+ TALLOC_FREE(dom_infos);
+ TALLOC_FREE(name_infos);
TALLOC_FREE(tmp_ctx);
return result;
}
@@ -823,16 +873,14 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **ret_domain, const char **ret_name,
- enum SID_NAME_USE *ret_type)
+ enum lsa_SidType *ret_type)
{
struct lsa_dom_info *domain;
struct lsa_name_info *name;
TALLOC_CTX *tmp_ctx;
BOOL ret = False;
- tmp_ctx = talloc_new(mem_ctx);
-
- if (tmp_ctx == NULL) {
+ if (!(tmp_ctx = talloc_new(mem_ctx))) {
DEBUG(0, ("talloc_new failed\n"));
return False;
}
@@ -846,12 +894,14 @@ BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
goto done;
}
- if (ret_domain != NULL) {
- *ret_domain = talloc_steal(mem_ctx, domain->name);
+ if ((ret_domain != NULL) &&
+ !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
+ goto done;
}
- if (ret_name != NULL) {
- *ret_name = talloc_steal(mem_ctx, name->name);
+ if ((ret_name != NULL) &&
+ !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
+ goto done;
}
if (ret_type != NULL) {
@@ -893,14 +943,14 @@ static struct uid_sid_cache {
struct uid_sid_cache *next, *prev;
uid_t uid;
DOM_SID sid;
- enum SID_NAME_USE sidtype;
+ enum lsa_SidType sidtype;
} *uid_sid_cache_head;
static struct gid_sid_cache {
struct gid_sid_cache *next, *prev;
gid_t gid;
DOM_SID sid;
- enum SID_NAME_USE sidtype;
+ enum lsa_SidType sidtype;
} *gid_sid_cache_head;
/*****************************************************************
@@ -1062,29 +1112,16 @@ void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
}
/*****************************************************************
- *THE CANONICAL* convert uid_t to SID function.
+ *THE LEGACY* convert uid_t to SID function.
*****************************************************************/
-void uid_to_sid(DOM_SID *psid, uid_t uid)
+void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
{
- uid_t low, high;
uint32 rid;
BOOL ret;
ZERO_STRUCTP(psid);
- if (fetch_sid_from_uid_cache(psid, uid))
- return;
-
- if ((lp_winbind_trusted_domains_only() ||
- (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high))) &&
- winbind_uid_to_sid(psid, uid)) {
-
- DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
- (unsigned int)uid, sid_string_static(psid)));
- goto done;
- }
-
become_root_uid_only();
ret = pdb_uid_to_rid(uid, &rid);
unbecome_root_uid_only();
@@ -1101,7 +1138,7 @@ void uid_to_sid(DOM_SID *psid, uid_t uid)
uid_to_unix_users_sid(uid, psid);
done:
- DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
+ DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
sid_string_static(psid)));
store_uid_sid_cache(psid, uid);
@@ -1109,28 +1146,15 @@ void uid_to_sid(DOM_SID *psid, uid_t uid)
}
/*****************************************************************
- *THE CANONICAL* convert gid_t to SID function.
+ *THE LEGACY* convert gid_t to SID function.
*****************************************************************/
-void gid_to_sid(DOM_SID *psid, gid_t gid)
+void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
{
BOOL ret;
- gid_t low, high;
ZERO_STRUCTP(psid);
- if (fetch_sid_from_gid_cache(psid, gid))
- return;
-
- if ((lp_winbind_trusted_domains_only() ||
- (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high))) &&
- winbind_gid_to_sid(psid, gid)) {
-
- DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
- (unsigned int)gid, sid_string_static(psid)));
- goto done;
- }
-
become_root_uid_only();
ret = pdb_gid_to_sid(gid, psid);
unbecome_root_uid_only();
@@ -1145,7 +1169,7 @@ void gid_to_sid(DOM_SID *psid, gid_t gid)
gid_to_unix_groups_sid(gid, psid);
done:
- DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
+ DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
sid_string_static(psid)));
store_gid_sid_cache(psid, gid);
@@ -1153,21 +1177,13 @@ void gid_to_sid(DOM_SID *psid, gid_t gid)
}
/*****************************************************************
- *THE CANONICAL* convert SID to uid function.
+ *THE LEGACY* convert SID to uid function.
*****************************************************************/
-BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
+BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
uint32 rid;
- gid_t gid;
-
- if (fetch_uid_from_cache(puid, psid))
- return True;
-
- if (fetch_gid_from_cache(&gid, psid)) {
- return False;
- }
if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
uid_t uid = rid;
@@ -1195,35 +1211,13 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
}
/* This was ours, but it was not mapped. Fail */
-
- return False;
- }
-
- if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
-
- if (type != SID_NAME_USER) {
- DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
- sid_string_static(psid),
- sid_type_lookup(type)));
- return False;
}
- if (!winbind_sid_to_uid(puid, psid)) {
- DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
- "new uid for sid %s\n",
- sid_string_static(psid)));
- return False;
- }
- goto done;
- }
-
- /* TODO: Here would be the place to allocate both a gid and a uid for
- * the SID in question */
-
+ DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
- done:
- DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
+done:
+ DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid),
(unsigned int)*puid ));
store_uid_sid_cache(psid, *puid);
@@ -1231,23 +1225,16 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
}
/*****************************************************************
- *THE CANONICAL* convert SID to gid function.
+ *THE LEGACY* convert SID to gid function.
Group mapping is used for gids that maps to Wellknown SIDs
*****************************************************************/
-BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
uint32 rid;
GROUP_MAP map;
union unid_t id;
- enum SID_NAME_USE type;
- uid_t uid;
-
- if (fetch_gid_from_cache(pgid, psid))
- return True;
-
- if (fetch_uid_from_cache(&uid, psid))
- return False;
+ enum lsa_SidType type;
if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
gid_t gid = rid;
@@ -1267,6 +1254,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
*pgid = map.gid;
goto done;
}
+ DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
}
@@ -1280,7 +1268,7 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
if (ret) {
if ((type != SID_NAME_DOM_GRP) &&
(type != SID_NAME_ALIAS)) {
- DEBUG(5, ("sid %s is a %s, expected a group\n",
+ DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
sid_string_static(psid),
sid_type_lookup(type)));
return False;
@@ -1290,37 +1278,146 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
}
/* This was ours, but it was not mapped. Fail */
+ }
+ DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
+
+ done:
+ DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
+ (unsigned int)*pgid ));
+
+ store_gid_sid_cache(psid, *pgid);
+
+ return True;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert uid_t to SID function.
+*****************************************************************/
+
+void uid_to_sid(DOM_SID *psid, uid_t uid)
+{
+ ZERO_STRUCTP(psid);
+
+ if (fetch_sid_from_uid_cache(psid, uid))
+ return;
+
+ if (!winbind_uid_to_sid(psid, uid)) {
+ if (!winbind_ping()) {
+ DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
+ legacy_uid_to_sid(psid, uid);
+ return;
+ }
+
+ DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
+ uid));
+ return;
}
- if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
- DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
- "then winbind)\n", sid_string_static(psid)));
+ DEBUG(10,("uid %u -> sid %s\n",
+ (unsigned int)uid, sid_string_static(psid)));
+
+ store_uid_sid_cache(psid, uid);
+ return;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert gid_t to SID function.
+*****************************************************************/
+
+void gid_to_sid(DOM_SID *psid, gid_t gid)
+{
+ ZERO_STRUCTP(psid);
+ if (fetch_sid_from_gid_cache(psid, gid))
+ return;
+
+ if (!winbind_gid_to_sid(psid, gid)) {
+ if (!winbind_ping()) {
+ DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
+ legacy_gid_to_sid(psid, gid);
+ return;
+ }
+
+ DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
+ gid));
+ return;
+ }
+
+ DEBUG(10,("gid %u -> sid %s\n",
+ (unsigned int)gid, sid_string_static(psid)));
+
+ store_gid_sid_cache(psid, gid);
+ return;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert SID to uid function.
+*****************************************************************/
+
+BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
+{
+ gid_t gid;
+
+ if (fetch_uid_from_cache(puid, psid))
+ return True;
+
+ if (fetch_gid_from_cache(&gid, psid)) {
return False;
}
- /* winbindd knows it; Ensure this is a group sid */
+ if (!winbind_sid_to_uid(puid, psid)) {
+ if (!winbind_ping()) {
+ DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
+ return legacy_sid_to_uid(psid, puid);
+ }
- if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
- (type != SID_NAME_WKN_GRP)) {
- DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
- "a %s\n", sid_type_lookup(type)));
+ DEBUG(5, ("winbind failed to find a uid for sid %s\n",
+ sid_string_static(psid)));
return False;
}
- /* winbindd knows it and it is a type of group; sid_to_gid must succeed
- or we are dead in the water */
+ /* TODO: Here would be the place to allocate both a gid and a uid for
+ * the SID in question */
+
+ DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
+ (unsigned int)*puid ));
+
+ store_uid_sid_cache(psid, *puid);
+ return True;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert SID to gid function.
+ Group mapping is used for gids that maps to Wellknown SIDs
+*****************************************************************/
+
+BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+{
+ uid_t uid;
+
+ if (fetch_gid_from_cache(pgid, psid))
+ return True;
+
+ if (fetch_uid_from_cache(&uid, psid))
+ return False;
+
+ /* Ask winbindd if it can map this sid to a gid.
+ * (Idmap will check it is a valid SID and of the right type) */
if ( !winbind_sid_to_gid(pgid, psid) ) {
- DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
- "for sid %s\n", sid_string_static(psid)));
+ if (!winbind_ping()) {
+ DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n"));
+ return legacy_sid_to_gid(psid, pgid);
+ }
+
+ DEBUG(10,("winbind failed to find a gid for sid %s\n",
+ sid_string_static(psid)));
return False;
}
- done:
- DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
+ DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
(unsigned int)*pgid ));
store_gid_sid_cache(psid, *pgid);
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 47b6b958000..d354a485c2d 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -50,10 +50,8 @@ const char *my_sam_name(void)
/**********************************************************************
***********************************************************************/
-static int samu_destroy(void *p)
+static int samu_destroy(struct samu *user)
{
- struct samu *user = p;
-
data_blob_clear_free( &user->lm_pw );
data_blob_clear_free( &user->nt_pw );
@@ -111,7 +109,7 @@ struct samu *samu_new( TALLOC_CTX *ctx )
user->profile_path = "";
user->acct_desc = "";
user->workstations = "";
- user->unknown_str = "";
+ user->comment = "";
user->munged_dial = "";
user->plaintext_pw = NULL;
@@ -348,9 +346,9 @@ void pdb_sethexpwd(char *p, const unsigned char *pwd, uint32 acct_ctrl)
slprintf(&p[i*2], 3, "%02X", pwd[i]);
} else {
if (acct_ctrl & ACB_PWNOTREQ)
- safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
+ safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
else
- safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
+ safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
}
}
@@ -553,7 +551,7 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
********************************************************************/
BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
GROUP_MAP map;
BOOL ret;
@@ -932,14 +930,15 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
if (homedir) {
fstrcpy( tmpstring, homedir );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_homedir(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_homedir(sampass,
- talloc_sub_basic(sampass, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT);
}
@@ -951,28 +950,29 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
if (logon_script) {
fstrcpy( tmpstring, logon_script );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_logon_script(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT);
}
if (profile_path) {
fstrcpy( tmpstring, profile_path );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_profile_path(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass, username, lp_logon_path()),
+ talloc_sub_basic(sampass, username, domain, lp_logon_path()),
PDB_DEFAULT);
}
@@ -996,7 +996,7 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen) {
- uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
+ uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
if (!pw_hist) {
ret = False;
goto done;
@@ -1023,7 +1023,6 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
}
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
- pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
pdb_set_hours_len(sampass, hours_len, PDB_SET);
pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
pdb_set_logon_count(sampass, logon_count, PDB_SET);
@@ -1107,7 +1106,7 @@ uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_onl
logoff_time = (uint32)pdb_get_logoff_time(sampass);
kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
bad_password_time = (uint32)pdb_get_bad_password_time(sampass);
- pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
+ pass_can_change_time = (uint32)pdb_get_pass_can_change_time_noncalc(sampass);
pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
@@ -1367,6 +1366,7 @@ BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
time_t LastBadPassword;
uint16 BadPasswordCount;
uint32 resettime;
+ BOOL res;
BadPasswordCount = pdb_get_bad_password_count(sampass);
if (!BadPasswordCount) {
@@ -1374,7 +1374,11 @@ BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
return True;
}
- if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) {
+ become_root();
+ res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
+ unbecome_root();
+
+ if (!res) {
DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
return False;
}
@@ -1407,6 +1411,7 @@ BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
{
uint32 duration;
time_t LastBadPassword;
+ BOOL res;
if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
@@ -1414,7 +1419,11 @@ BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
return True;
}
- if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) {
+ become_root();
+ res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
+ unbecome_root();
+
+ if (!res) {
DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
return False;
}
diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c
index f1b1a7673ca..62898f3dac8 100644
--- a/source/passdb/pdb_get_set.c
+++ b/source/passdb/pdb_get_set.c
@@ -72,12 +72,59 @@ time_t pdb_get_pass_last_set_time(const struct samu *sampass)
time_t pdb_get_pass_can_change_time(const struct samu *sampass)
{
+ uint32 allow;
+
+ /* if the last set time is zero, it means the user cannot
+ change their password, and this time must be zero. jmcd
+ */
+ if (sampass->pass_last_set_time == 0)
+ return (time_t) 0;
+
+ /* if the time is max, and the field has been changed,
+ we're trying to update this real value from the sampass
+ to indicate that the user cannot change their password. jmcd
+ */
+ if (sampass->pass_can_change_time == get_time_t_max() &&
+ pdb_get_init_flags(sampass, PDB_CANCHANGETIME) == PDB_CHANGED)
+ return sampass->pass_can_change_time;
+
+ if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &allow))
+ allow = 0;
+
+ /* in normal cases, just calculate it from policy */
+ return sampass->pass_last_set_time + allow;
+}
+
+/* we need this for loading from the backend, so that we don't overwrite
+ non-changed max times, otherwise the pass_can_change checking won't work */
+time_t pdb_get_pass_can_change_time_noncalc(const struct samu *sampass)
+{
return sampass->pass_can_change_time;
}
time_t pdb_get_pass_must_change_time(const struct samu *sampass)
{
- return sampass->pass_must_change_time;
+ uint32 expire;
+
+ if (sampass->pass_last_set_time == 0)
+ return (time_t) 0;
+
+ if (sampass->acct_ctrl & ACB_PWNOEXP)
+ return get_time_t_max();
+
+ if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
+ || expire == (uint32)-1 || expire == 0)
+ return get_time_t_max();
+
+ return sampass->pass_last_set_time + expire;
+}
+
+BOOL pdb_get_pass_can_change(const struct samu *sampass)
+{
+ if (sampass->pass_can_change_time == get_time_t_max() &&
+ sampass->pass_last_set_time != 0)
+ return False;
+ return True;
}
uint16 pdb_get_logon_divs(const struct samu *sampass)
@@ -166,7 +213,7 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass)
}
if ( pdb_gid_to_sid(pwd->pw_gid, gsid) ) {
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
+ enum lsa_SidType type = SID_NAME_UNKNOWN;
TALLOC_CTX *mem_ctx = talloc_init("pdb_get_group_sid");
BOOL lookup_ret;
@@ -288,9 +335,9 @@ const char *pdb_get_workstations(const struct samu *sampass)
return sampass->workstations;
}
-const char *pdb_get_unknown_str(const struct samu *sampass)
+const char *pdb_get_comment(const struct samu *sampass)
{
- return sampass->unknown_str;
+ return sampass->comment;
}
const char *pdb_get_munged_dial(const struct samu *sampass)
@@ -752,23 +799,22 @@ BOOL pdb_set_workstations(struct samu *sampass, const char *workstations, enum p
}
/*********************************************************************
- Set the user's 'unknown_str', whatever the heck this actually is...
********************************************************************/
-BOOL pdb_set_unknown_str(struct samu *sampass, const char *unknown_str, enum pdb_value_state flag)
+BOOL pdb_set_comment(struct samu *sampass, const char *comment, enum pdb_value_state flag)
{
- if (unknown_str) {
- sampass->unknown_str = talloc_strdup(sampass, unknown_str);
+ if (comment) {
+ sampass->comment = talloc_strdup(sampass, comment);
- if (!sampass->unknown_str) {
- DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
+ if (!sampass->comment) {
+ DEBUG(0, ("pdb_set_comment: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->unknown_str = PDB_NOT_QUITE_NULL;
+ sampass->comment = PDB_NOT_QUITE_NULL;
}
- return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
+ return pdb_set_init_flags(sampass, PDB_COMMENT, flag);
}
/*********************************************************************
@@ -925,43 +971,14 @@ BOOL pdb_set_backend_private_data(struct samu *sampass, void *private_data,
/* Helpful interfaces to the above */
-/*********************************************************************
- Sets the last changed times and must change times for a normal
- password change.
- ********************************************************************/
-
-BOOL pdb_set_pass_changed_now(struct samu *sampass)
+BOOL pdb_set_pass_can_change(struct samu *sampass, BOOL canchange)
{
- uint32 expire;
- uint32 min_age;
-
- if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
- return False;
-
- if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
- || (expire==(uint32)-1) || (expire == 0)) {
- if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
- return False;
- } else {
- if (!pdb_set_pass_must_change_time (sampass,
- pdb_get_pass_last_set_time(sampass)
- + expire, PDB_CHANGED))
- return False;
- }
-
- if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age)
- || (min_age==(uint32)-1)) {
- if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
- return False;
- } else {
- if (!pdb_set_pass_can_change_time (sampass,
- pdb_get_pass_last_set_time(sampass)
- + min_age, PDB_CHANGED))
- return False;
- }
- return True;
+ return pdb_set_pass_can_change_time(sampass,
+ canchange ? 0 : get_time_t_max(),
+ PDB_CHANGED);
}
+
/*********************************************************************
Set the user's PLAINTEXT password. Used as an interface to the above.
Also sets the last change time to NOW.
@@ -997,7 +1014,7 @@ BOOL pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED))
return False;
- if (!pdb_set_pass_changed_now (sampass))
+ if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
return False;
/* Store the password history. */
@@ -1021,7 +1038,7 @@ BOOL pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
if (current_history_len < pwHistLen) {
/* Ensure we have space for the needed history. */
- uchar *new_history = TALLOC(sampass,
+ uchar *new_history = (uchar *)TALLOC(sampass,
pwHistLen*PW_HISTORY_ENTRY_LEN);
if (!new_history) {
return False;
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index 8fefd989114..ba251bc4cfb 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -46,45 +46,8 @@ static void lazy_initialize_passdb(void)
static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
const char **name,
- enum SID_NAME_USE *psid_name_use,
+ enum lsa_SidType *psid_name_use,
union unid_t *unix_id);
-/*******************************************************************
- Clean up uninitialised passwords. The only way to tell
- that these values are not 'real' is that they do not
- have a valid last set time. Instead, the value is fixed at 0.
- Therefore we use that as the key for 'is this a valid password'.
- However, it is perfectly valid to have a 'default' last change
- time, such LDAP with a missing attribute would produce.
-********************************************************************/
-
-static void pdb_force_pw_initialization(struct samu *pass)
-{
- 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
- is ignored */
-
- if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT)
- && (pdb_get_pass_last_set_time(pass) == 0) )
- {
-
- if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT)
- {
- lm_pwd = pdb_get_lanman_passwd(pass);
- if (lm_pwd)
- pdb_set_lanman_passwd(pass, NULL, PDB_CHANGED);
- }
- if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT)
- {
- nt_pwd = pdb_get_nt_passwd(pass);
- if (nt_pwd)
- pdb_set_nt_passwd(pass, NULL, PDB_CHANGED);
- }
- }
-
- return;
-}
NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init)
{
@@ -250,7 +213,7 @@ BOOL pdb_getsampwent(struct samu *user)
if ( !NT_STATUS_IS_OK(pdb->getsampwent(pdb, user) ) ) {
return False;
}
- pdb_force_pw_initialization( user );
+
return True;
}
@@ -266,8 +229,6 @@ BOOL pdb_getsampwnam(struct samu *sam_acct, const char *username)
TALLOC_FREE(csamuser);
}
- pdb_force_pw_initialization( sam_acct );
-
csamuser = samu_new( NULL );
if (!csamuser) {
return False;
@@ -369,6 +330,15 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
if (add_ret == 0) {
smb_nscd_flush_user_cache();
}
+
+#ifdef ENABLE_BUILD_FARM_HACKS
+ if (add_ret != 0) {
+ DEBUG(1, ("Creating a faked user %s for build farm "
+ "purposes\n", name));
+ faked_create_user(name);
+ }
+#endif
+
flush_pwnam_cache();
pwd = Get_Pwnam_alloc(tmp_ctx, name);
@@ -693,7 +663,7 @@ NTSTATUS pdb_delete_group_mapping_entry(DOM_SID sid)
return pdb->delete_group_mapping_entry(pdb, sid);
}
-BOOL pdb_enum_group_mapping(const DOM_SID *sid, enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
+BOOL pdb_enum_group_mapping(const DOM_SID *sid, enum lsa_SidType sid_name_use, GROUP_MAP **pp_rmap,
size_t *p_num_entries, BOOL unix_only)
{
struct pdb_methods *pdb = pdb_get_methods();
@@ -985,34 +955,57 @@ NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid,
int num_rids,
uint32 *rids,
const char **names,
- uint32 *attrs)
+ enum lsa_SidType *attrs)
{
struct pdb_methods *pdb = pdb_get_methods();
- return pdb->lookup_rids(pdb, domain_sid,
- num_rids, rids, names, attrs);
+ return pdb->lookup_rids(pdb, domain_sid, num_rids, rids, names, attrs);
}
+/*
+ * NOTE: pdb_lookup_names is currently (2007-01-12) not used anywhere
+ * in the samba code.
+ * Unlike _lsa_lookup_sids and _samr_lookup_rids, which eventually
+ * also ask pdb_lookup_rids, thus looking up a bunch of rids at a time,
+ * the pdb_ calls _lsa_lookup_names and _samr_lookup_names come
+ * down to are pdb_getsampwnam and pdb_getgrnam instead of
+ * pdb_lookup_names.
+ * But in principle, it the call belongs to the API and might get
+ * used in this context some day.
+ */
+#if 0
NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid,
int num_names,
const char **names,
uint32 *rids,
- uint32 *attrs)
+ enum lsa_SidType *attrs)
{
struct pdb_methods *pdb = pdb_get_methods();
- return pdb->lookup_names(pdb, domain_sid,
- num_names, names, rids, attrs);
+ return pdb->lookup_names(pdb, domain_sid, num_names, names, rids, attrs);
}
+#endif
BOOL pdb_get_account_policy(int policy_index, uint32 *value)
{
struct pdb_methods *pdb = pdb_get_methods();
- return NT_STATUS_IS_OK(pdb->get_account_policy(pdb, policy_index, value));
+ NTSTATUS status;
+
+ become_root();
+ status = pdb->get_account_policy(pdb, policy_index, value);
+ unbecome_root();
+
+ return NT_STATUS_IS_OK(status);
}
BOOL pdb_set_account_policy(int policy_index, uint32 value)
{
struct pdb_methods *pdb = pdb_get_methods();
- return NT_STATUS_IS_OK(pdb->set_account_policy(pdb, policy_index, value));
+ NTSTATUS status;
+
+ become_root();
+ status = pdb->set_account_policy(pdb, policy_index, value);
+ unbecome_root();
+
+ return NT_STATUS_IS_OK(status);
}
BOOL pdb_get_seq_num(time_t *seq_num)
@@ -1027,6 +1020,12 @@ BOOL pdb_uid_to_rid(uid_t uid, uint32 *rid)
return pdb->uid_to_rid(pdb, uid, rid);
}
+BOOL pdb_uid_to_sid(uid_t uid, DOM_SID *sid)
+{
+ struct pdb_methods *pdb = pdb_get_methods();
+ return pdb->uid_to_sid(pdb, uid, sid);
+}
+
BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid)
{
struct pdb_methods *pdb = pdb_get_methods();
@@ -1034,7 +1033,7 @@ BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid)
}
BOOL pdb_sid_to_id(const DOM_SID *sid, union unid_t *id,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
struct pdb_methods *pdb = pdb_get_methods();
return pdb->sid_to_id(pdb, sid, id, type);
@@ -1057,7 +1056,7 @@ BOOL pdb_new_rid(uint32 *rid)
{
struct pdb_methods *pdb = pdb_get_methods();
const char *name = NULL;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
uint32 allocated_rid = 0;
int i;
TALLOC_CTX *ctx;
@@ -1193,8 +1192,8 @@ static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq
return NT_STATUS_OK;
}
-static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid,
- uint32 *rid)
+static BOOL pdb_default_uid_to_sid(struct pdb_methods *methods, uid_t uid,
+ DOM_SID *sid)
{
struct samu *sampw = NULL;
struct passwd *unix_pw;
@@ -1225,15 +1224,31 @@ static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid,
return False;
}
- ret = sid_peek_check_rid(get_global_sam_sid(),
- pdb_get_user_sid(sampw), rid);
+ sid_copy(sid, pdb_get_user_sid(sampw));
+
+ TALLOC_FREE(sampw);
+
+ return True;
+}
+
+static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid,
+ uint32 *rid)
+{
+ DOM_SID sid;
+ BOOL ret;
+
+ ret = pdb_default_uid_to_sid(methods, uid, &sid);
+ if (!ret) {
+ return ret;
+ }
+
+ ret = sid_peek_check_rid(get_global_sam_sid(), &sid, rid);
if (!ret) {
DEBUG(1, ("Could not peek rid out of sid %s\n",
- sid_string_static(pdb_get_user_sid(sampw))));
+ sid_string_static(&sid)));
}
- TALLOC_FREE(sampw);
return ret;
}
@@ -1252,7 +1267,7 @@ static BOOL pdb_default_gid_to_sid(struct pdb_methods *methods, gid_t gid,
static BOOL pdb_default_sid_to_id(struct pdb_methods *methods,
const DOM_SID *sid,
- union unid_t *id, enum SID_NAME_USE *type)
+ union unid_t *id, enum lsa_SidType *type)
{
TALLOC_CTX *mem_ctx;
BOOL ret = False;
@@ -1303,23 +1318,24 @@ static BOOL pdb_default_sid_to_id(struct pdb_methods *methods,
return ret;
}
-static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
+static BOOL add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
uid_t uid, uid_t **pp_uids, size_t *p_num)
{
size_t i;
for (i=0; i<*p_num; i++) {
if ((*pp_uids)[i] == uid)
- return;
+ return True;
}
*pp_uids = TALLOC_REALLOC_ARRAY(mem_ctx, *pp_uids, uid_t, *p_num+1);
if (*pp_uids == NULL)
- return;
+ return False;
(*pp_uids)[*p_num] = uid;
*p_num += 1;
+ return True;
}
static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size_t *p_num)
@@ -1328,6 +1344,7 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
char **gr;
struct passwd *pwd;
BOOL winbind_env;
+ BOOL ret = False;
*pp_uids = NULL;
*p_num = 0;
@@ -1338,19 +1355,17 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
if ((grp = getgrgid(gid)) == NULL) {
/* allow winbindd lookups, but only if they weren't already disabled */
- if (!winbind_env) {
- winbind_on();
- }
-
- return False;
+ goto done;
}
/* Primary group members */
setpwent();
while ((pwd = getpwent()) != NULL) {
if (pwd->pw_gid == gid) {
- add_uid_to_array_unique(mem_ctx, pwd->pw_uid,
- pp_uids, p_num);
+ if (!add_uid_to_array_unique(mem_ctx, pwd->pw_uid,
+ pp_uids, p_num)) {
+ goto done;
+ }
}
}
endpwent();
@@ -1361,18 +1376,24 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
if (pw == NULL)
continue;
- add_uid_to_array_unique(mem_ctx, pw->pw_uid, pp_uids, p_num);
+ if (!add_uid_to_array_unique(mem_ctx, pw->pw_uid, pp_uids, p_num)) {
+ goto done;
+ }
}
+ ret = True;
+
+ done:
+
/* allow winbindd lookups, but only if they weren't already disabled */
if (!winbind_env) {
winbind_on();
}
- return True;
+ return ret;
}
-NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
+static NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
TALLOC_CTX *mem_ctx,
const DOM_SID *group,
uint32 **pp_member_rids,
@@ -1414,7 +1435,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
return NT_STATUS_OK;
}
-NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
+static NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
TALLOC_CTX *mem_ctx,
struct samu *user,
DOM_SID **pp_sids,
@@ -1466,7 +1487,7 @@ NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
const char **name,
- enum SID_NAME_USE *psid_name_use,
+ enum lsa_SidType *psid_name_use,
union unid_t *unix_id)
{
struct samu *sam_account = NULL;
@@ -1553,12 +1574,12 @@ static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
return False;
}
-NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
+static NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
const DOM_SID *domain_sid,
int num_rids,
uint32 *rids,
const char **names,
- uint32 *attrs)
+ enum lsa_SidType *attrs)
{
int i;
NTSTATUS result;
@@ -1616,12 +1637,13 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
return result;
}
-NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
+#if 0
+static NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
const DOM_SID *domain_sid,
int num_names,
const char **names,
uint32 *rids,
- uint32 *attrs)
+ enum lsa_SidType *attrs)
{
int i;
NTSTATUS result;
@@ -1672,6 +1694,7 @@ NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
return result;
}
+#endif
static struct pdb_search *pdb_search_init(enum pdb_search_type type)
{
@@ -1738,7 +1761,7 @@ struct user_search {
static BOOL next_entry_users(struct pdb_search *s,
struct samr_displayentry *entry)
{
- struct user_search *state = s->private_data;
+ struct user_search *state = (struct user_search *)s->private_data;
struct samu *user = NULL;
next:
@@ -1813,7 +1836,7 @@ struct group_search {
static BOOL next_entry_groups(struct pdb_search *s,
struct samr_displayentry *entry)
{
- struct group_search *state = s->private_data;
+ struct group_search *state = (struct group_search *)s->private_data;
uint32 rid;
GROUP_MAP *map = &state->groups[state->current_group];
@@ -1831,12 +1854,13 @@ static BOOL next_entry_groups(struct pdb_search *s,
static void search_end_groups(struct pdb_search *search)
{
- struct group_search *state = search->private_data;
+ struct group_search *state =
+ (struct group_search *)search->private_data;
SAFE_FREE(state->groups);
}
static BOOL pdb_search_grouptype(struct pdb_search *search,
- const DOM_SID *sid, enum SID_NAME_USE type)
+ const DOM_SID *sid, enum lsa_SidType type)
{
struct group_search *state;
@@ -2040,6 +2064,7 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
(*methods)->set_account_policy = pdb_default_set_account_policy;
(*methods)->get_seq_num = pdb_default_get_seq_num;
(*methods)->uid_to_rid = pdb_default_uid_to_rid;
+ (*methods)->uid_to_sid = pdb_default_uid_to_sid;
(*methods)->gid_to_sid = pdb_default_gid_to_sid;
(*methods)->sid_to_id = pdb_default_sid_to_id;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 54c250033dd..533b936efd9 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -650,12 +650,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
{
pdb_set_homedir( sampass,
- talloc_sub_basic(sampass, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, homedir );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_homedir(sampass, tmpstring, PDB_SET);
@@ -665,12 +666,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
{
pdb_set_logon_script( sampass,
- talloc_sub_basic(sampass, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, logon_script );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_logon_script(sampass, tmpstring, PDB_SET);
@@ -680,12 +682,13 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
{
pdb_set_profile_path( sampass,
- talloc_sub_basic( sampass, username, lp_logon_path()),
+ talloc_sub_basic( sampass, username, domain,
+ lp_logon_path()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, profile_path );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_profile_path(sampass, tmpstring, PDB_SET);
@@ -787,7 +790,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
- if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
+ if ((pwhist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
return False;
}
@@ -967,15 +970,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
/* only update the RID if we actually need to */
if (need_update(sampass, PDB_USERSID)) {
fstring sid_string;
- fstring dom_sid_string;
const DOM_SID *user_sid = pdb_get_user_sid(sampass);
switch ( ldap_state->schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
- sid_to_string(sid_string, user_sid),
- sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+ sid_string_static(user_sid),
+ sid_string_static(&ldap_state->domain_sid)));
return False;
}
slprintf(temp, sizeof(temp) - 1, "%i", rid);
@@ -1001,15 +1003,14 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
if (need_update(sampass, PDB_GROUPSID)) {
fstring sid_string;
- fstring dom_sid_string;
const DOM_SID *group_sid = pdb_get_group_sid(sampass);
switch ( ldap_state->schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
- sid_to_string(sid_string, group_sid),
- sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+ sid_string_static(group_sid),
+ sid_string_static(&ldap_state->domain_sid)));
return False;
}
@@ -1095,7 +1096,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
- slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
+ slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time_noncalc(sampass));
if (need_update(sampass, PDB_CANCHANGETIME))
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
@@ -1592,12 +1593,14 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
}
if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
+ SAFE_FREE(utf8_password);
return NT_STATUS_NO_MEMORY;
}
if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
DEBUG(0,("ber_alloc_t returns NULL\n"));
SAFE_FREE(utf8_password);
+ SAFE_FREE(utf8_dn);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1747,7 +1750,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struc
LDAPMod **mods = NULL;
const char **attr_list;
- result = pdb_get_backend_private_data(newpwd, my_methods);
+ result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
if (pdb_get_username(newpwd) == NULL) {
@@ -2159,7 +2162,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
return False;
}
- map->sid_name_use = (enum SID_NAME_USE)atol(temp);
+ map->sid_name_use = (enum lsa_SidType)atol(temp);
if ((map->sid_name_use < SID_NAME_USER) ||
(map->sid_name_use > SID_NAME_UNKNOWN)) {
@@ -2467,8 +2470,11 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
sid_peek_rid(&sid, &rid);
- add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
- p_num_members);
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+ p_num_members)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
}
@@ -2503,8 +2509,11 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
goto done;
}
- add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
- p_num_members);
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+ p_num_members)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
ret = NT_STATUS_OK;
@@ -2586,7 +2595,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
primary_gid = strtoul(gidstr, NULL, 10);
break;
default:
- DEBUG(1, ("found more than one accoutn with the same user name ?!\n"));
+ DEBUG(1, ("found more than one account with the same user name ?!\n"));
ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
}
@@ -2615,11 +2624,17 @@ 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(mem_ctx, primary_gid, pp_gids, &num_gids);
+ if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
/* This sid will be replaced later */
- add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
+ if (!add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
for (entry = ldap_first_entry(conn->ldap_struct, result);
entry != NULL;
@@ -2651,10 +2666,16 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
if (gid == primary_gid) {
sid_copy(&(*pp_sids)[0], &sid);
} else {
- add_gid_to_array_unique(mem_ctx, gid, pp_gids,
- &num_gids);
- add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
- &num_sids);
+ if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
+ &num_gids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ if (!add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
+ &num_sids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
}
@@ -3107,7 +3128,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
*********************************************************************/
static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
- const DOM_SID *domsid, enum SID_NAME_USE sid_name_use,
+ const DOM_SID *domsid, enum lsa_SidType sid_name_use,
GROUP_MAP **pp_rmap,
size_t *p_num_entries,
BOOL unix_only)
@@ -3169,7 +3190,7 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
int count;
LDAPMod **mods = NULL;
int rc;
- enum SID_NAME_USE type = SID_NAME_USE_NONE;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
pstring filter;
@@ -3281,7 +3302,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
int i;
pstring filter;
size_t num_members = 0;
- enum SID_NAME_USE type = SID_NAME_USE_NONE;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
*pp_members = NULL;
*p_num_members = 0;
@@ -3351,7 +3372,11 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
if (!string_to_sid(&member, values[i]))
continue;
- add_sid_to_array(NULL, &member, pp_members, &num_members);
+ if (!add_sid_to_array(NULL, &member, pp_members, &num_members)) {
+ ldap_value_free(values);
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
*p_num_members = num_members;
@@ -3380,7 +3405,7 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
int i;
int rc;
char *filter;
- enum SID_NAME_USE type = SID_NAME_USE_NONE;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
if (sid_check_is_builtin(domain_sid)) {
type = SID_NAME_ALIAS;
@@ -3439,8 +3464,11 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
if (!sid_peek_check_rid(domain_sid, &sid, &rid))
continue;
- add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
- p_num_alias_rids);
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
+ p_num_alias_rids)) {
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
ldap_msgfree(result);
@@ -3460,8 +3488,6 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- const char *attrs[2];
-
DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
if (!ldap_state->domain_dn) {
@@ -3475,9 +3501,6 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
return ntstatus;
}
- attrs[0] = policy_attr;
- attrs[1] = NULL;
-
slprintf(value_string, sizeof(value_string) - 1, "%i", value);
smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
@@ -3503,11 +3526,6 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
int policy_index, uint32 value)
{
- if (!account_policy_migrated(False)) {
- return (account_policy_set(policy_index, value)) ?
- NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
- }
-
return ldapsam_set_account_policy_in_ldap(methods, policy_index,
value);
}
@@ -3596,11 +3614,6 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
- if (!account_policy_migrated(False)) {
- return (account_policy_get(policy_index, value))
- ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
- }
-
if (cache_account_policy_get(policy_index, value)) {
DEBUG(11,("ldapsam_get_account_policy: got valid value from "
"cache\n"));
@@ -3652,7 +3665,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
int num_rids,
uint32 *rids,
const char **names,
- uint32 *attrs)
+ enum lsa_SidType *attrs)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
@@ -3802,7 +3815,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
uint32 rid;
int rid_index;
const char *attr;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
@@ -3813,7 +3826,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
continue;
}
- type = atol(attr);
+ type = (enum lsa_SidType)atol(attr);
/* Consistency checks */
if ((is_builtin && (type != SID_NAME_ALIAS)) ||
@@ -3940,7 +3953,8 @@ struct ldap_search_state {
static BOOL ldapsam_search_firstpage(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
LDAP *ld;
int rc = LDAP_OPERATIONS_ERROR;
@@ -3992,7 +4006,8 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search)
static BOOL ldapsam_search_nextpage(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
int rc;
if (!state->connection->paged_results) {
@@ -4022,7 +4037,8 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
static BOOL ldapsam_search_next_entry(struct pdb_search *search,
struct samr_displayentry *entry)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
BOOL result;
retry:
@@ -4057,7 +4073,8 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
static void ldapsam_search_end(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
int rc;
if (state->pagedresults_cookie == NULL)
@@ -4173,7 +4190,8 @@ static BOOL ldapsam_search_users(struct pdb_methods *methods,
struct pdb_search *search,
uint32 acct_flags)
{
- struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
struct ldap_search_state *state;
state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4329,9 +4347,10 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
struct pdb_search *search,
const DOM_SID *sid,
- enum SID_NAME_USE type)
+ enum lsa_SidType type)
{
- struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
struct ldap_search_state *state;
state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
@@ -4490,8 +4509,8 @@ static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *ri
int i;
for (i=0; i<10; i++) {
- NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
- rid);
+ NTSTATUS result = ldapsam_get_new_rid(
+ (struct ldapsam_privates *)methods->private_data, rid);
if (NT_STATUS_IS_OK(result)) {
return result;
}
@@ -4515,9 +4534,10 @@ static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
const DOM_SID *sid,
- union unid_t *id, enum SID_NAME_USE *type)
+ union unid_t *id, enum lsa_SidType *type)
{
- struct ldapsam_privates *priv = methods->private_data;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)methods->private_data;
char *filter;
const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
NULL };
@@ -4577,7 +4597,7 @@ static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
}
id->gid = strtoul(gid_str, NULL, 10);
- *type = strtoul(value, NULL, 10);
+ *type = (enum lsa_SidType)strtoul(value, NULL, 10);
ret = True;
goto done;
}
@@ -5504,7 +5524,7 @@ NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *lo
(*pdb_method)->name = "ldapsam_compat";
- ldap_state = (*pdb_method)->private_data;
+ ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
@@ -5567,7 +5587,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
}
}
- ldap_state = (*pdb_method)->private_data;
+ ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
/* Try to setup the Domain Name, Domain SID, algorithmic rid base */
diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c
index 08ad96efa4b..ab4a1a7f208 100644
--- a/source/passdb/pdb_nds.c
+++ b/source/passdb/pdb_nds.c
@@ -241,7 +241,7 @@ static int berDecodeLoginData(
if(retData)
{
retOctStrLen = *retDataLen + 1;
- retOctStr = SMB_MALLOC(retOctStrLen);
+ retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
if(!retOctStr)
{
err = LDAP_OPERATIONS_ERROR;
@@ -404,7 +404,7 @@ static int nmasldap_get_simple_pwd(
size_t pwdBufLen, bufferLen;
bufferLen = pwdBufLen = pwdLen+2;
- pwdBuf = SMB_MALLOC(pwdBufLen); /* digest and null */
+ pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */
if(pwdBuf == NULL)
{
return LDAP_NO_MEMORY;
@@ -568,7 +568,7 @@ static int nmasldap_get_password(
}
bufferLen = pwdBufLen = *pwdSize;
- pwdBuf = SMB_MALLOC(pwdBufLen+2);
+ pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2);
if(pwdBuf == NULL)
{
return LDAP_NO_MEMORY;
@@ -769,7 +769,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n",
success ? "Successful" : "Failed", username));
- result = pdb_get_backend_private_data(sam_acct, methods);
+ result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods);
if (!result) {
attr_list = get_userattr_list(NULL,
ldap_state->schema_ver);
@@ -854,7 +854,8 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
{
- struct ldapsam_privates *ldap_state = (*pdb_method)->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)((*pdb_method)->private_data);
/* Mark this as eDirectory ldap */
ldap_state->is_nds_ldap = True;
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index 1bc6813603e..e01b4b1855c 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -64,6 +64,52 @@ struct smbpasswd_privates
enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
+static SIG_ATOMIC_T gotalarm;
+
+/***************************************************************
+ Signal function to tell us we timed out.
+****************************************************************/
+
+static void gotalarm_sig(void)
+{
+ gotalarm = 1;
+}
+
+/***************************************************************
+ Lock or unlock a fd for a known lock type. Abandon after waitsecs
+ seconds.
+****************************************************************/
+
+static BOOL do_file_lock(int fd, int waitsecs, int type)
+{
+ SMB_STRUCT_FLOCK lock;
+ int ret;
+ void (*oldsig_handler)(int);
+
+ gotalarm = 0;
+ oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+
+ lock.l_type = type;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ lock.l_pid = 0;
+
+ alarm(waitsecs);
+ /* Note we must *NOT* use sys_fcntl here ! JRA */
+ ret = fcntl(fd, SMB_F_SETLKW, &lock);
+ alarm(0);
+ CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
+
+ if (gotalarm) {
+ DEBUG(0, ("do_file_lock: failed to %s file.\n",
+ type == F_UNLCK ? "unlock" : "lock"));
+ return False;
+ }
+
+ return (ret == 0);
+}
+
/***************************************************************
Lock an fd. Abandon after waitsecs seconds.
****************************************************************/
@@ -584,7 +630,8 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
Routine to add an entry to the smbpasswd file.
*************************************************************************/
-static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
+static NTSTATUS add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state,
+ struct smb_passwd *newpwd)
{
const char *pfile = smbpasswd_state->smbpasswd_file;
struct smb_passwd *pwd = NULL;
@@ -605,7 +652,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
if (fp == NULL) {
DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
- return False;
+ return map_nt_error_from_unix(errno);
}
/*
@@ -616,7 +663,7 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
if (strequal(newpwd->smb_name, pwd->smb_name)) {
DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
- return False;
+ return NT_STATUS_USER_EXISTS;
}
}
@@ -630,17 +677,18 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
fd = fileno(fp);
if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) {
+ NTSTATUS result = map_nt_error_from_unix(errno);
DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
- return False;
+ return result;
}
if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
- return False;
+ return NT_STATUS_NO_MEMORY;
}
new_entry_length = strlen(new_entry);
@@ -651,6 +699,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
#endif
if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
+ NTSTATUS result = map_nt_error_from_unix(errno);
DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
@@ -663,12 +712,12 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
free(new_entry);
- return False;
+ return result;
}
free(new_entry);
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
- return True;
+ return NT_STATUS_OK;
}
/************************************************************************
@@ -1080,7 +1129,8 @@ static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
size_t new_entry_length;
if (strequal(name, pwd->smb_name)) {
- DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
+ DEBUG(10, ("del_smbfilepwd_entry: found entry with "
+ "name %s - deleting it.\n", name));
continue;
}
@@ -1308,7 +1358,7 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
struct smb_passwd *smb_pw;
- void *fp = NULL;
+ FILE *fp = NULL;
DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
@@ -1352,7 +1402,7 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct sam
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
struct smb_passwd *smb_pw;
- void *fp = NULL;
+ FILE *fp = NULL;
fstring sid_str;
uint32 rid;
@@ -1423,11 +1473,7 @@ static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct
}
/* add the entry */
- if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- return NT_STATUS_OK;
+ return add_smbfilepwd_entry(smbpasswd_state, &smb_pw);
}
static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index 262e68eb007..e9beaa05368 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -169,7 +169,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
}
else {
pdb_set_homedir(sampass,
- talloc_sub_basic(sampass, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT);
}
@@ -177,7 +178,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
else {
pdb_set_dir_drive(sampass,
- talloc_sub_basic(sampass, username, lp_logon_drive()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_drive()),
PDB_DEFAULT);
}
@@ -185,7 +187,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_logon_script(sampass, logon_script, PDB_SET);
else {
pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT);
}
@@ -193,7 +196,8 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_profile_path(sampass, profile_path, PDB_SET);
} else {
pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass, username, lp_logon_path()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_path()),
PDB_DEFAULT);
}
@@ -356,7 +360,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
}
else {
pdb_set_homedir(sampass,
- talloc_sub_basic(sampass, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT);
}
@@ -364,7 +369,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
else {
pdb_set_dir_drive(sampass,
- talloc_sub_basic(sampass, username, lp_logon_drive()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_drive()),
PDB_DEFAULT);
}
@@ -372,7 +378,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_logon_script(sampass, logon_script, PDB_SET);
else {
pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT);
}
@@ -380,7 +387,8 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf
pdb_set_profile_path(sampass, profile_path, PDB_SET);
} else {
pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass, username, lp_logon_path()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_path()),
PDB_DEFAULT);
}
@@ -541,14 +549,15 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
if (homedir) {
fstrcpy( tmpstring, homedir );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_homedir(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_homedir(sampass,
- talloc_sub_basic(sampass, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT);
}
@@ -560,28 +569,30 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
if (logon_script) {
fstrcpy( tmpstring, logon_script );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_logon_script(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT);
}
if (profile_path) {
fstrcpy( tmpstring, profile_path );
if (expand_explicit) {
- standard_sub_basic( username, tmpstring,
+ standard_sub_basic( username, domain, tmpstring,
sizeof(tmpstring) );
}
pdb_set_profile_path(sampass, tmpstring, PDB_SET);
}
else {
pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass, username, lp_logon_path()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_path()),
PDB_DEFAULT);
}
@@ -606,7 +617,7 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
/* Change from V1 is addition of password history field. */
pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen) {
- uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
+ uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
if (!pw_hist) {
ret = False;
goto done;
@@ -901,7 +912,7 @@ static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
/* save a copy of the key */
- ptr->key.dptr = memdup( key.dptr, key.dsize );
+ ptr->key.dptr = (char *)memdup( key.dptr, key.dsize );
if (!ptr->key.dptr) {
DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
/* just return 0 and let the traversal continue */
diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c
index 04d6da2814a..3ac3a932338 100644
--- a/source/passdb/secrets.c
+++ b/source/passdb/secrets.c
@@ -104,8 +104,9 @@ BOOL secrets_store(const char *key, const void *data, size_t size)
secrets_init();
if (!tdb)
return False;
- return tdb_store(tdb, string_tdb_data(key), make_tdb_data(data, size),
- TDB_REPLACE) == 0;
+ return tdb_trans_store(tdb, string_tdb_data(key),
+ make_tdb_data((const char *)data, size),
+ TDB_REPLACE) == 0;
}
@@ -157,39 +158,39 @@ BOOL secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
return True;
}
-BOOL secrets_store_domain_guid(const char *domain, struct uuid *guid)
+BOOL secrets_store_domain_guid(const char *domain, struct GUID *guid)
{
fstring key;
slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
strupper_m(key);
- return secrets_store(key, guid, sizeof(struct uuid));
+ return secrets_store(key, guid, sizeof(struct GUID));
}
-BOOL secrets_fetch_domain_guid(const char *domain, struct uuid *guid)
+BOOL secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
{
- struct uuid *dyn_guid;
+ struct GUID *dyn_guid;
fstring key;
size_t size = 0;
- struct uuid new_guid;
+ struct GUID new_guid;
slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
strupper_m(key);
- dyn_guid = (struct uuid *)secrets_fetch(key, &size);
+ dyn_guid = (struct GUID *)secrets_fetch(key, &size);
if (!dyn_guid) {
if (lp_server_role() == ROLE_DOMAIN_PDC) {
smb_uuid_generate_random(&new_guid);
if (!secrets_store_domain_guid(domain, &new_guid))
return False;
- dyn_guid = (struct uuid *)secrets_fetch(key, &size);
+ dyn_guid = (struct GUID *)secrets_fetch(key, &size);
}
if (dyn_guid == NULL) {
return False;
}
}
- if (size != sizeof(struct uuid)) {
+ if (size != sizeof(struct GUID)) {
DEBUG(1,("UUID size %d is wrong!\n", (int)size));
SAFE_FREE(dyn_guid);
return False;
@@ -207,7 +208,7 @@ BOOL secrets_fetch_domain_guid(const char *domain, struct uuid *guid)
*
* @return stored password's key
**/
-const char *trust_keystr(const char *domain)
+static const char *trust_keystr(const char *domain)
{
static fstring keystr;
@@ -288,7 +289,8 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
return True;
}
- if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
+ if (!(pass = (struct machine_acct_pass *)secrets_fetch(
+ trust_keystr(domain), &size))) {
DEBUG(5, ("secrets_fetch failed!\n"));
return False;
}
@@ -319,6 +321,136 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
return True;
}
+/**
+ * Pack SID passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of packing buffer
+ * @param sid pointer to sid to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+static size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx;
+ size_t len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num,
+ sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "b",
+ sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_pack(pack_buf + len, bufsize - len, "d",
+ sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
+/**
+ * Unpack SID into a pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param sid pointer to sid structure to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+static size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid)
+{
+ int idx, len = 0;
+
+ if (!sid || !pack_buf) return -1;
+
+ len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
+ &sid->sid_rev_num, &sid->num_auths);
+
+ for (idx = 0; idx < 6; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "b",
+ &sid->id_auth[idx]);
+ }
+
+ for (idx = 0; idx < MAXSUBAUTHS; idx++) {
+ len += tdb_unpack(pack_buf + len, bufsize - len, "d",
+ &sid->sub_auths[idx]);
+ }
+
+ return len;
+}
+
+/**
+ * Pack TRUSTED_DOM_PASS passed by pointer
+ *
+ * @param pack_buf pointer to buffer which is to be filled with packed data
+ * @param bufsize size of the buffer
+ * @param pass pointer to trusted domain password to be packed
+ *
+ * @return length of the packed representation of the whole structure
+ **/
+static size_t tdb_trusted_dom_pass_pack(char* pack_buf, int bufsize,
+ TRUSTED_DOM_PASS* pass)
+{
+ int idx, len = 0;
+
+ if (!pack_buf || !pass) return -1;
+
+ /* packing unicode domain name and password */
+ len += tdb_pack(pack_buf + len, bufsize - len, "d",
+ pass->uni_name_len);
+
+ for (idx = 0; idx < 32; idx++)
+ len += tdb_pack(pack_buf + len, bufsize - len, "w",
+ pass->uni_name[idx]);
+
+ len += tdb_pack(pack_buf + len, bufsize - len, "dPd", pass->pass_len,
+ pass->pass, pass->mod_time);
+
+ /* packing SID structure */
+ len += tdb_sid_pack(pack_buf + len, bufsize - len, &pass->domain_sid);
+
+ return len;
+}
+
+
+/**
+ * Unpack TRUSTED_DOM_PASS passed by pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param pass pointer to trusted domain password to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+static size_t tdb_trusted_dom_pass_unpack(char* pack_buf, int bufsize,
+ TRUSTED_DOM_PASS* pass)
+{
+ int idx, len = 0;
+
+ if (!pack_buf || !pass) return -1;
+
+ /* unpack unicode domain name and plaintext password */
+ len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
+
+ for (idx = 0; idx < 32; idx++)
+ len += tdb_unpack(pack_buf + len, bufsize - len, "w",
+ &pass->uni_name[idx]);
+
+ len += tdb_unpack(pack_buf + len, bufsize - len, "dPd",
+ &pass->pass_len, &pass->pass, &pass->mod_time);
+
+ /* unpack domain sid */
+ len += tdb_sid_unpack(pack_buf + len, bufsize - len,
+ &pass->domain_sid);
+
+ return len;
+}
+
/************************************************************************
Routine to get account password to trusted domain
************************************************************************/
@@ -336,7 +468,8 @@ BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
ZERO_STRUCT(pass);
/* fetching trusted domain password structure */
- if (!(pass_buf = secrets_fetch(trustdom_keystr(domain), &size))) {
+ if (!(pass_buf = (char *)secrets_fetch(trustdom_keystr(domain),
+ &size))) {
DEBUG(5, ("secrets_fetch failed!\n"));
return False;
}
@@ -494,7 +627,7 @@ char *secrets_fetch_machine_password(const char *domain,
uint32 *last_set_time;
asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
strupper_m(key);
- last_set_time = secrets_fetch(key, &size);
+ last_set_time = (unsigned int *)secrets_fetch(key, &size);
if (last_set_time) {
*pass_last_set_time = IVAL(last_set_time,0);
SAFE_FREE(last_set_time);
@@ -509,7 +642,7 @@ char *secrets_fetch_machine_password(const char *domain,
uint32 *channel_type;
asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
strupper_m(key);
- channel_type = secrets_fetch(key, &size);
+ channel_type = (unsigned int *)secrets_fetch(key, &size);
if (channel_type) {
*channel = IVAL(channel_type,0);
SAFE_FREE(channel_type);
@@ -613,7 +746,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
}
- *pw=secrets_fetch(key, &size);
+ *pw=(char *)secrets_fetch(key, &size);
SAFE_FREE(key);
if (!size) {
@@ -631,7 +764,7 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
for (p=old_style_key; *p; p++)
if (*p == ',') *p = '/';
- data=secrets_fetch(old_style_key, &size);
+ data=(char *)secrets_fetch(old_style_key, &size);
if (!size && size < sizeof(old_style_pw)) {
DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
SAFE_FREE(old_style_key);
@@ -672,20 +805,35 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
{
TDB_LIST_NODE *keys, *k;
char *pattern;
+ TALLOC_CTX *tmp_ctx;
+
+ if (!(tmp_ctx = talloc_new(mem_ctx))) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
/* generate searching pattern */
- pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
+ pattern = talloc_asprintf(tmp_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
if (pattern == NULL) {
DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() "
"failed!\n"));
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
- *domains = NULL;
*num_domains = 0;
+ /*
+ * Make sure that a talloc context for the trustdom_info structs
+ * exists
+ */
+
+ if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
/* fetching trusted domains' data and collecting them in a list */
keys = tdb_search_keys(tdb, pattern);
@@ -698,16 +846,17 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
struct trustdom_info *dom_info;
/* important: ensure null-termination of the key string */
- secrets_key = talloc_strndup(mem_ctx,
+ secrets_key = talloc_strndup(tmp_ctx,
k->node_key.dptr,
k->node_key.dsize);
if (!secrets_key) {
DEBUG(0, ("strndup failed!\n"));
tdb_search_list_free(keys);
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
- packed_pass = secrets_fetch(secrets_key, &size);
+ packed_pass = (char *)secrets_fetch(secrets_key, &size);
packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size,
&pass);
/* packed representation isn't needed anymore */
@@ -727,30 +876,31 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
continue;
}
- dom_info = TALLOC_P(mem_ctx, struct trustdom_info);
- if (dom_info == NULL) {
+ if (!(dom_info = TALLOC_P(*domains, struct trustdom_info))) {
DEBUG(0, ("talloc failed\n"));
tdb_search_list_free(keys);
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
- if (pull_ucs2_talloc(mem_ctx, &dom_info->name,
+ if (pull_ucs2_talloc(dom_info, &dom_info->name,
pass.uni_name) == (size_t)-1) {
DEBUG(2, ("pull_ucs2_talloc failed\n"));
tdb_search_list_free(keys);
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
sid_copy(&dom_info->sid, &pass.domain_sid);
- ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info,
+ ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
domains, num_domains);
if (*domains == NULL) {
tdb_search_list_free(keys);
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
- talloc_steal(*domains, dom_info);
}
DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n",
@@ -758,6 +908,7 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
/* free the results of searching the keys */
tdb_search_list_free(keys);
+ TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
}
@@ -858,9 +1009,9 @@ BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result)
*******************************************************************************/
void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
{
- *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
- *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
- *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+ *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
+ *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+ *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
if (*username && **username) {
@@ -965,7 +1116,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
pdc->remote_machine,
pdc->domain);
- value.dptr = TALLOC(mem_ctx, value.dsize);
+ value.dptr = (char *)TALLOC(mem_ctx, value.dsize);
if (!value.dptr) {
TALLOC_FREE(keystr);
return False;
@@ -1101,3 +1252,45 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
return True;
}
+
+BOOL secrets_store_generic(const char *owner, const char *key, const char *secret)
+{
+ char *tdbkey = NULL;
+ BOOL ret;
+
+ if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
+ DEBUG(0, ("asprintf failed!\n"));
+ return False;
+ }
+
+ ret = secrets_store(tdbkey, secret, strlen(secret)+1);
+
+ SAFE_FREE(tdbkey);
+ return ret;
+}
+
+/*******************************************************************
+ Find the ldap password.
+******************************************************************/
+
+char *secrets_fetch_generic(const char *owner, const char *key)
+{
+ char *secret = NULL;
+ char *tdbkey = NULL;
+
+ if (( ! owner) || ( ! key)) {
+ DEBUG(1, ("Invalid Paramters"));
+ return NULL;
+ }
+
+ if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NULL;
+ }
+
+ secret = (char *)secrets_fetch(tdbkey, NULL);
+ SAFE_FREE(tdbkey);
+
+ return secret;
+}
+
diff --git a/source/po/fi.msg b/source/po/fi.msg
new file mode 100644
index 00000000000..7206ac71a03
--- /dev/null
+++ b/source/po/fi.msg
@@ -0,0 +1,611 @@
+# Finnish messages for international release of SWAT.
+# Copyright (C) 2007 Lauri Nurmi <lanurmi@iki.fi>
+#
+# 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.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: i18n_swat \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-01-02 01:56+0200\n"
+"PO-Revision-Date: 2007-01-12 18:56+0200\n"
+"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
+"Language-Team: Finnish <laatu@lokalisointi.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: \n"
+
+#: ../web/swat.c:139
+#, c-format
+msgid "ERROR: Can't open %s"
+msgstr "VIRHE: Avaaminen ei onnistu — %s"
+
+#: ../web/swat.c:223
+msgid "Help"
+msgstr "Ohje"
+
+#: ../web/swat.c:229 ../web/swat.c:254 ../web/swat.c:275 ../web/swat.c:285 ../web/swat.c:294 ../web/swat.c:303 ../web/swat.c:309 ../web/swat.c:315 ../web/swat.c:328
+msgid "Set Default"
+msgstr "Oletusarvo"
+
+#: ../web/swat.c:450
+#, c-format
+msgid "failed to open %s for writing"
+msgstr "avaaminen kirjoitustilassa ei onnistu — %s"
+
+#: ../web/swat.c:473
+#, c-format
+msgid "Can't reload %s"
+msgstr "Uudelleen lataaminen ei onnistu — %s"
+
+#: ../web/swat.c:543
+#, c-format
+msgid "Logged in as <b>%s</b>"
+msgstr "Sisäänkirjautuminen käyttäjänä <b>%s</b>"
+
+#: ../web/swat.c:547
+msgid "Home"
+msgstr "Koti"
+
+#: ../web/swat.c:549
+msgid "Globals"
+msgstr "Yleiset"
+
+#: ../web/swat.c:550
+msgid "Shares"
+msgstr "Jaot"
+
+#: ../web/swat.c:551
+msgid "Printers"
+msgstr "Tulostimet"
+
+#: ../web/swat.c:552
+msgid "Wizard"
+msgstr "Ohjatut asetukset"
+
+#: ../web/swat.c:556
+msgid "Status"
+msgstr "Tila"
+
+#: ../web/swat.c:557
+msgid "View Config"
+msgstr "Näytä asetukset"
+
+#: ../web/swat.c:559
+msgid "Password Management"
+msgstr "Salasanojen hallinta"
+
+#: ../web/swat.c:569
+msgid "Current View Is"
+msgstr "Näkymä nyt"
+
+#: ../web/swat.c:570 ../web/swat.c:573
+msgid "Basic"
+msgstr "Tavallinen"
+
+#: ../web/swat.c:571 ../web/swat.c:574
+msgid "Advanced"
+msgstr "Laajennettu"
+
+#: ../web/swat.c:572
+msgid "Change View To"
+msgstr "Vaihda näkymäksi"
+
+#: ../web/swat.c:601
+msgid "Current Config"
+msgstr "Nykyiset asetukset"
+
+#: ../web/swat.c:605
+msgid "Normal View"
+msgstr "Normaali näkymä"
+
+#: ../web/swat.c:607
+msgid "Full View"
+msgstr "Täysi näkymä"
+
+#. Here we first set and commit all the parameters that were selected
+#. in the previous screen.
+#: ../web/swat.c:626
+msgid "Wizard Parameter Edit Page"
+msgstr "Ohjattujen asetusten muokkaussivu"
+
+#: ../web/swat.c:655
+msgid "Note: smb.conf file has been read and rewritten"
+msgstr "Huom: smb.conf-tiedosto on luettu ja kirjoitettu uudelleen"
+
+#. Here we go ...
+#: ../web/swat.c:763
+msgid "Samba Configuration Wizard"
+msgstr "Samban ohjatut asetukset"
+
+#: ../web/swat.c:767
+msgid "The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."
+msgstr "â€Kirjoita uudelleen smb.conf-tiedostoâ€-painike tyhjentää oletusarvot ja kommentit smb.conf-tiedostosta."
+
+#: ../web/swat.c:768
+msgid "The same will happen if you press the commit button."
+msgstr "Samoin tapahtuu â€Tallennaâ€-painiketta painettaessa."
+
+#: ../web/swat.c:771
+msgid "Rewrite smb.conf file"
+msgstr "Kirjoita uudelleen smb.conf-tiedosto"
+
+#: ../web/swat.c:772
+msgid "Commit"
+msgstr "Tallenna"
+
+#: ../web/swat.c:773
+msgid "Edit Parameter Values"
+msgstr "Muokkaa asetusten arvoja"
+
+#: ../web/swat.c:779
+msgid "Server Type"
+msgstr "Palvelimen tyyppi"
+
+#: ../web/swat.c:780
+msgid "Stand Alone"
+msgstr "Itsenäinen"
+
+# lähde: Microsoftin käännökset
+#: ../web/swat.c:781
+msgid "Domain Member"
+msgstr "Toimialuejäsen"
+
+# lähde: Microsoftin käännökset
+#: ../web/swat.c:782
+msgid "Domain Controller"
+msgstr "Toimialueen ohjauskone"
+
+#: ../web/swat.c:785
+msgid "Unusual Type in smb.conf - Please Select New Mode"
+msgstr "Epätavallinen tyyppi smb.confissa — Valitse uusi tila"
+
+#: ../web/swat.c:787
+msgid "Configure WINS As"
+msgstr "WINS"
+
+#: ../web/swat.c:788
+msgid "Not Used"
+msgstr "Ei käytössä"
+
+#: ../web/swat.c:789
+msgid "Server for client use"
+msgstr "Palvelimena"
+
+#: ../web/swat.c:790
+msgid "Client of another WINS server"
+msgstr "Käyttää WINS-etäpalvelinta"
+
+#: ../web/swat.c:792
+msgid "Remote WINS Server"
+msgstr "WINS-etäpalvelin"
+
+#: ../web/swat.c:803
+msgid "Error: WINS Server Mode and WINS Support both set in smb.conf"
+msgstr "Virhe: Sekä WINS-palvelintila että WINS-tuki asetettu smb.confissa"
+
+#: ../web/swat.c:804
+msgid "Please Select desired WINS mode above."
+msgstr "Valitse haluttu WINSin tila yltä."
+
+#: ../web/swat.c:806
+msgid "Expose Home Directories"
+msgstr "Jaa kotihakemistot"
+
+#: ../web/swat.c:821
+msgid "The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."
+msgstr "Yllä olevat valinnat asettavat useita asetuksia, ja auttavat Samban nopeassa käyttöönotossa."
+
+#: ../web/swat.c:834
+msgid "Global Parameters"
+msgstr "Yleisasetukset"
+
+#: ../web/swat.c:862 ../web/swat.c:966 ../web/swat.c:1318
+msgid "Commit Changes"
+msgstr "Tallenna muutokset"
+
+#: ../web/swat.c:866 ../web/swat.c:969 ../web/swat.c:1320
+msgid "Reset Values"
+msgstr "Kumoa muutokset"
+
+#: ../web/swat.c:891
+msgid "Share Parameters"
+msgstr "Jakoasetukset"
+
+#: ../web/swat.c:934
+msgid "Choose Share"
+msgstr "Valitse jako"
+
+#: ../web/swat.c:951
+msgid "Delete Share"
+msgstr "Poista jako"
+
+#: ../web/swat.c:958
+msgid "Create Share"
+msgstr "Luo jako"
+
+#: ../web/swat.c:994
+msgid "password change in demo mode rejected"
+msgstr "salasanan muutos estetty esittelytilassa"
+
+#: ../web/swat.c:1007
+msgid "Can't setup password database vectors."
+msgstr "Salasanatietokannan alustus epäonnistui."
+
+#: ../web/swat.c:1033
+msgid " Must specify \"User Name\" "
+msgstr " Käyttäjätunnus on annettava "
+
+#: ../web/swat.c:1049
+msgid " Must specify \"Old Password\" "
+msgstr " Vanha salasana on annettava "
+
+#: ../web/swat.c:1055
+msgid " Must specify \"Remote Machine\" "
+msgstr " Etäkone on annettava "
+
+#: ../web/swat.c:1062
+msgid " Must specify \"New, and Re-typed Passwords\" "
+msgstr " Uusi salasana on kirjoitettava kahdesti "
+
+#: ../web/swat.c:1068
+msgid " Re-typed password didn't match new password "
+msgstr " Salasanat eivät täsmää "
+
+#: ../web/swat.c:1101
+#, c-format
+msgid " The passwd for '%s' has been changed."
+msgstr " Käyttäjän â€%s†salasana vaihdettu."
+
+#: ../web/swat.c:1104
+#, c-format
+msgid " The passwd for '%s' has NOT been changed."
+msgstr " Käyttäjän â€%s†salasanaa EI vaihdettu."
+
+#: ../web/swat.c:1129
+msgid "Server Password Management"
+msgstr "Palvelimen salasanojen hallinta"
+
+#.
+#. * Create all the dialog boxes for data collection
+#.
+#: ../web/swat.c:1138 ../web/swat.c:1185
+msgid "User Name"
+msgstr "Käyttäjätunnus"
+
+#: ../web/swat.c:1141 ../web/swat.c:1187
+msgid "Old Password"
+msgstr "Vanha salasana"
+
+#: ../web/swat.c:1144 ../web/swat.c:1189
+msgid "New Password"
+msgstr "Uusi salasana"
+
+#: ../web/swat.c:1146 ../web/swat.c:1191
+msgid "Re-type New Password"
+msgstr "Uusi salasana uudelleen"
+
+#: ../web/swat.c:1154 ../web/swat.c:1202
+msgid "Change Password"
+msgstr "Vaihda salasana"
+
+#: ../web/swat.c:1157
+msgid "Add New User"
+msgstr "Lisää uusi käyttäjä"
+
+#: ../web/swat.c:1159
+msgid "Delete User"
+msgstr "Poista käyttäjä"
+
+# Joku suomenkielisempi olisi ehkä parempi.
+#: ../web/swat.c:1161
+msgid "Disable User"
+msgstr "Passivoi käyttäjä"
+
+# Joku suomenkielisempi olisi ehkä parempi.
+#: ../web/swat.c:1163
+msgid "Enable User"
+msgstr "Aktivoi käyttäjä"
+
+# hmm...
+#: ../web/swat.c:1176
+msgid "Client/Server Password Management"
+msgstr "Asiakas-palvelin-salasanojen hallinta"
+
+#: ../web/swat.c:1193
+msgid "Remote Machine"
+msgstr "Etäkone"
+
+#: ../web/swat.c:1232
+msgid "Printer Parameters"
+msgstr "Tulostinasetukset"
+
+#: ../web/swat.c:1234
+msgid "Important Note:"
+msgstr "Tärkeä huomautus:"
+
+#: ../web/swat.c:1235
+#, c-format
+msgid "Printer names marked with [*] in the Choose Printer drop-down box "
+msgstr "Tähdellä [*] merkityt tulostimien nimet pudotusvalikossa ovat "
+
+#: ../web/swat.c:1236
+#, c-format
+msgid "are autoloaded printers from "
+msgstr "automaattisesti ladattuja tulostimia "
+
+#: ../web/swat.c:1237
+msgid "Printcap Name"
+msgstr "Printcap Name -asetuksen osoittamasta paikasta"
+
+#: ../web/swat.c:1238
+msgid "Attempting to delete these printers from SWAT will have no effect."
+msgstr "Näiden tulostimien poistaminen ei onnistu SWATin kautta."
+
+#: ../web/swat.c:1284
+msgid "Choose Printer"
+msgstr "Valitse tulostin"
+
+#: ../web/swat.c:1303
+msgid "Delete Printer"
+msgstr "Poista tulostin"
+
+#: ../web/swat.c:1310
+msgid "Create Printer"
+msgstr "Luo tulostin"
+
+#: ../web/statuspage.c:139
+msgid "RDWR "
+msgstr "Luku+kirj. "
+
+#: ../web/statuspage.c:141
+msgid "WRONLY "
+msgstr "Vain kirj. "
+
+#: ../web/statuspage.c:143
+msgid "RDONLY "
+msgstr "Vain luku "
+
+#: ../web/statuspage.c:330
+msgid "Server Status"
+msgstr "Palvelimen tila"
+
+#: ../web/statuspage.c:335
+msgid "Auto Refresh"
+msgstr "Automaattinen päivitys"
+
+#: ../web/statuspage.c:336 ../web/statuspage.c:341
+msgid "Refresh Interval: "
+msgstr "Päivitysväli: "
+
+#: ../web/statuspage.c:340
+msgid "Stop Refreshing"
+msgstr "Lopeta päivitys"
+
+#: ../web/statuspage.c:355
+msgid "version:"
+msgstr "versio:"
+
+#: ../web/statuspage.c:358
+msgid "smbd:"
+msgstr "smbd:"
+
+#: ../web/statuspage.c:358 ../web/statuspage.c:371 ../web/statuspage.c:385
+msgid "running"
+msgstr "käynnissä"
+
+#: ../web/statuspage.c:358 ../web/statuspage.c:371 ../web/statuspage.c:385
+msgid "not running"
+msgstr "pysäytetty"
+
+#: ../web/statuspage.c:362
+msgid "Stop smbd"
+msgstr "Pysäytä smbd"
+
+#: ../web/statuspage.c:364
+msgid "Start smbd"
+msgstr "Käynnistä smbd"
+
+#: ../web/statuspage.c:366
+msgid "Restart smbd"
+msgstr "Käynnistä smbd uudelleen"
+
+#: ../web/statuspage.c:371
+msgid "nmbd:"
+msgstr "nmbd:"
+
+#: ../web/statuspage.c:375
+msgid "Stop nmbd"
+msgstr "Pysäytä nmbd"
+
+#: ../web/statuspage.c:377
+msgid "Start nmbd"
+msgstr "Käynnistä nmbd"
+
+#: ../web/statuspage.c:379
+msgid "Restart nmbd"
+msgstr "Käynnistä nmbd uudelleen"
+
+#: ../web/statuspage.c:385
+msgid "winbindd:"
+msgstr "winbindd:"
+
+#: ../web/statuspage.c:389
+msgid "Stop winbindd"
+msgstr "Pysäytä winbindd"
+
+#: ../web/statuspage.c:391
+msgid "Start winbindd"
+msgstr "Käynnistä winbindd"
+
+#: ../web/statuspage.c:393
+msgid "Restart winbindd"
+msgstr "Käynnistä winbindd uudelleen"
+
+#. stop, restart all
+#: ../web/statuspage.c:402
+msgid "Stop All"
+msgstr "Pysäytä kaikki"
+
+#: ../web/statuspage.c:403
+msgid "Restart All"
+msgstr "Käynnistä kaikki uudelleen"
+
+#. start all
+#: ../web/statuspage.c:407
+msgid "Start All"
+msgstr "Käynnistä kaikki"
+
+#: ../web/statuspage.c:414
+msgid "Active Connections"
+msgstr "Aktiiviset yhteydet"
+
+#: ../web/statuspage.c:416 ../web/statuspage.c:429 ../web/statuspage.c:437
+msgid "PID"
+msgstr "PID"
+
+#: ../web/statuspage.c:416 ../web/statuspage.c:429
+msgid "Client"
+msgstr "Asiakas"
+
+#: ../web/statuspage.c:416
+msgid "IP address"
+msgstr "IP-osoite"
+
+#: ../web/statuspage.c:416 ../web/statuspage.c:429 ../web/statuspage.c:437
+msgid "Date"
+msgstr "Aika"
+
+#: ../web/statuspage.c:418
+msgid "Kill"
+msgstr "Sulje"
+
+#: ../web/statuspage.c:426
+msgid "Active Shares"
+msgstr "Aktiiviset jaot"
+
+#: ../web/statuspage.c:429
+msgid "Share"
+msgstr "Jako"
+
+#: ../web/statuspage.c:429
+msgid "User"
+msgstr "Käyttäjä"
+
+#: ../web/statuspage.c:429
+msgid "Group"
+msgstr "Ryhmä"
+
+#: ../web/statuspage.c:435
+msgid "Open Files"
+msgstr "Avoimet tiedostot"
+
+# Tämä on ilmeisesti palvelimen puolella vallitseva UID.
+#: ../web/statuspage.c:437
+msgid "Sharing"
+msgstr "Jakaja"
+
+#: ../web/statuspage.c:437
+msgid "R/W"
+msgstr "Luku/kirj."
+
+# Selitys:
+# "Oplocks is a unique Windows file locking feature. It is not really file
+# locking, but is included in most discussions of Windows file locking, so
+# is considered a de facto locking feature."
+# Suomennos: ???
+#: ../web/statuspage.c:437
+msgid "Oplock"
+msgstr "Oplock"
+
+#: ../web/statuspage.c:437
+msgid "File"
+msgstr "Tiedosto"
+
+#: ../web/statuspage.c:446
+msgid "Show Client in col 1"
+msgstr "Näytä asiakas 1. sarakkeessa"
+
+#: ../web/statuspage.c:447
+msgid "Show PID in col 1"
+msgstr "Näytä PID 1. sarakkeessa"
+
+#: ../param/loadparm.c:834
+msgid "Base Options"
+msgstr "Perusasetukset"
+
+#: ../param/loadparm.c:853
+msgid "Security Options"
+msgstr "Turvallisuusasetukset"
+
+#: ../param/loadparm.c:943
+msgid "Logging Options"
+msgstr "Lokiasetukset"
+
+#: ../param/loadparm.c:959
+msgid "Protocol Options"
+msgstr "Protokolla-asetukset"
+
+#: ../param/loadparm.c:1005
+msgid "Tuning Options"
+msgstr "Hienosäätöasetukset"
+
+#: ../param/loadparm.c:1035
+msgid "Printing Options"
+msgstr "Tulostusasetukset"
+
+#: ../param/loadparm.c:1072
+msgid "Filename Handling"
+msgstr "Tiedostonimien käsittely"
+
+#: ../param/loadparm.c:1102
+msgid "Domain Options"
+msgstr "Toimialueasetukset"
+
+#: ../param/loadparm.c:1106
+msgid "Logon Options"
+msgstr "Kirjautumisasetukset"
+
+#: ../param/loadparm.c:1127
+msgid "Browse Options"
+msgstr "Selausasetukset"
+
+#: ../param/loadparm.c:1141
+msgid "WINS Options"
+msgstr "WINS-asetukset"
+
+#: ../param/loadparm.c:1150
+msgid "Locking Options"
+msgstr "Lukitusasetukset"
+
+#: ../param/loadparm.c:1168
+msgid "Ldap Options"
+msgstr "LDAP-asetukset"
+
+#: ../param/loadparm.c:1184
+msgid "Miscellaneous Options"
+msgstr "Sekalaiset asetukset"
+
+#: ../param/loadparm.c:1189
+msgid "EventLog Options"
+msgstr "Tapahtumalokiasetukset"
+
+#: ../param/loadparm.c:1257
+msgid "VFS module options"
+msgstr "VFS-moduulin asetukset"
+
+#: ../param/loadparm.c:1267
+msgid "Winbind options"
+msgstr "Winbind-asetukset"
diff --git a/source/popt/findme.c b/source/popt/findme.c
index a950e50018b..b28981ba1f4 100644
--- a/source/popt/findme.c
+++ b/source/popt/findme.c
@@ -22,8 +22,8 @@ const char * findProgramPath(const char * argv0) {
if (path == NULL) return NULL;
- start = pathbuf = alloca(strlen(path) + 1);
- buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
+ start = pathbuf = (char *)alloca(strlen(path) + 1);
+ buf = (char *)malloc(strlen(path) + strlen(argv0) + sizeof("/"));
if (buf == NULL) return NULL; /* XXX can't happen */
strcpy(pathbuf, path);
diff --git a/source/popt/popt.c b/source/popt/popt.c
index ce3687fb64e..d9e8411b9f2 100644
--- a/source/popt/popt.c
+++ b/source/popt/popt.c
@@ -51,7 +51,7 @@ static char * strerror(int errno) {
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
{
- con->execPath = _free(con->execPath);
+ con->execPath = (const char *)_free(con->execPath);
con->execPath = xstrdup(path);
con->execAbsolute = allowAbsolute;
/*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
@@ -68,7 +68,7 @@ static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
if (opt->arg == NULL) continue; /* XXX program error. */
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
/* Recurse on included sub-tables. */
- invokeCallbacksPRE(con, opt->arg);
+ invokeCallbacksPRE(con, (const struct poptOption *)opt->arg);
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
(opt->argInfo & POPT_CBFLAG_PRE))
{ /*@-castfcnptr@*/
@@ -91,7 +91,7 @@ static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
if (opt->arg == NULL) continue; /* XXX program error. */
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
/* Recurse on included sub-tables. */
- invokeCallbacksPOST(con, opt->arg);
+ invokeCallbacksPOST(con, (const struct poptOption *)opt->arg);
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
(opt->argInfo & POPT_CBFLAG_POST))
{ /*@-castfcnptr@*/
@@ -119,7 +119,8 @@ static void invokeCallbacksOPTION(poptContext con,
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
/* Recurse on included sub-tables. */
if (opt->arg != NULL) /* XXX program error */
- invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
+ invokeCallbacksOPTION(con, (const struct poptOption *)opt->arg,
+ myOpt, myData, shorty);
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
!(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
/* Save callback info. */
@@ -153,7 +154,7 @@ static void invokeCallbacksOPTION(poptContext con,
poptContext poptGetContext(const char * name, int argc, const char ** argv,
const struct poptOption * options, int flags)
{
- poptContext con = malloc(sizeof(*con));
+ poptContext con = (poptContext)malloc(sizeof(*con));
if (con == NULL) return NULL; /* XXX can't happen */
memset(con, 0, sizeof(*con));
@@ -168,7 +169,8 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
if (!(flags & POPT_CONTEXT_KEEP_FIRST))
con->os->next = 1; /* skip argv[0] */
- con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
+ con->leftovers = (const char **)calloc( (argc + 1),
+ sizeof(*con->leftovers) );
/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
con->options = options;
/*@=dependenttrans =assignexpose@*/
@@ -178,7 +180,8 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
con->execs = NULL;
con->numExecs = 0;
con->finalArgvAlloced = argc * 2;
- con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
+ con->finalArgv = (const char **)calloc( con->finalArgvAlloced,
+ sizeof(*con->finalArgv) );
con->execAbsolute = 1;
con->arg_strip = NULL;
@@ -186,7 +189,7 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
if (name) {
- char * t = malloc(strlen(name) + 1);
+ char * t = (char *)malloc(strlen(name) + 1);
if (t) con->appName = strcpy(t, name);
}
@@ -202,9 +205,9 @@ static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
/*@releases os->nextArg, os->argv, os->argb @*/
/*@modifies os @*/
{
- os->nextArg = _free(os->nextArg);
- os->argv = _free(os->argv);
- os->argb = PBM_FREE(os->argb);
+ os->nextArg = (const char *)_free(os->nextArg);
+ os->argv = (const char **)_free(os->argv);
+ os->argb = (pbm_set *)PBM_FREE(os->argb);
}
/*@-boundswrite@*/
@@ -216,7 +219,7 @@ void poptResetContext(poptContext con)
while (con->os > con->optionStack) {
cleanOSE(con->os--);
}
- con->os->argb = PBM_FREE(con->os->argb);
+ con->os->argb = (pbm_set *)PBM_FREE(con->os->argb);
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
@@ -230,12 +233,12 @@ void poptResetContext(poptContext con)
if (con->finalArgv != NULL)
for (i = 0; i < con->finalArgvCount; i++) {
/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
- con->finalArgv[i] = _free(con->finalArgv[i]);
+ con->finalArgv[i] = (const char *)_free(con->finalArgv[i]);
/*@=unqualifiedtrans@*/
}
con->finalArgvCount = 0;
- con->arg_strip = PBM_FREE(con->arg_strip);
+ con->arg_strip = ( pbm_set *)PBM_FREE(con->arg_strip);
/*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
return;
/*@=nullstate@*/
@@ -280,13 +283,13 @@ static int handleExec(/*@special@*/ poptContext con,
time 'round */
if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
con->finalArgvAlloced += 10;
- con->finalArgv = realloc(con->finalArgv,
+ con->finalArgv = (const char **)realloc(con->finalArgv,
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
i = con->finalArgvCount++;
if (con->finalArgv != NULL) /* XXX can't happen */
- { char *s = malloc((longName ? strlen(longName) : 0) + 3);
+ { char *s = (char *)malloc((longName ? strlen(longName) : 0) + 3);
if (s != NULL) { /* XXX can't happen */
if (longName)
sprintf(s, "--%s", longName);
@@ -375,12 +378,13 @@ static int execCommand(poptContext con)
(!con->execAbsolute && strchr(item->argv[0], '/')))
return POPT_ERROR_NOARG;
- argv = malloc(sizeof(*argv) *
- (6 + item->argc + con->numLeftovers + con->finalArgvCount));
+ argv = (const char **)malloc(
+ sizeof(*argv) * (6 + item->argc + con->numLeftovers + con->finalArgvCount));
if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */
if (!strchr(item->argv[0], '/') && con->execPath) {
- char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
+ char *s = (char *)alloca(
+ strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
sprintf(s, "%s/%s", con->execPath, item->argv[0]);
argv[argc] = s;
} else {
@@ -443,8 +447,12 @@ if (_popt_debug)
#endif
rc = execvp(argv[0], (char *const *)argv);
-
- return POPT_ERROR_ERRNO;
+ /* notreached */
+ if (rc) {
+ return POPT_ERROR_ERRNO;
+ }
+
+ return 0;
}
/*@=bounds =boundswrite @*/
@@ -470,7 +478,8 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
/* Recurse on included sub-tables. */
if (opt->arg == NULL) continue; /* XXX program error */
- opt2 = findOption(opt->arg, longName, shortName, callback,
+ opt2 = findOption((const struct poptOption *)opt->arg, longName,
+ shortName, callback,
callbackData, singleDash);
if (opt2 == NULL) continue;
/* Sub-table data will be inheirited if no data yet. */
@@ -542,7 +551,7 @@ static const char * findNextArg(/*@special@*/ poptContext con,
/*@innercontinue@*/ continue;
arg = os->argv[i];
if (delete_arg) {
- if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
+ if (os->argb == NULL) os->argb = (pbm_set *)PBM_ALLOC(os->argc);
if (os->argb != NULL) /* XXX can't happen */
PBM_SET(i, os->argb);
}
@@ -567,7 +576,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
size_t tn = strlen(s) + 1;
char c;
- te = t = malloc(tn);;
+ te = t = (char *)malloc(tn);;
if (t == NULL) return NULL; /* XXX can't happen */
while ((c = *s++) != '\0') {
switch (c) {
@@ -589,7 +598,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
alen = strlen(a);
tn += alen;
*te = '\0';
- t = realloc(t, tn);
+ t = (char *)realloc(t, tn);
te = t + strlen(t);
strncpy(te, a, alen); te += alen;
continue;
@@ -600,7 +609,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
*te++ = c;
}
*te = '\0';
- t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
+ t = (char *)realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
return t;
}
/*@=boundswrite@*/
@@ -612,7 +621,7 @@ static void poptStripArg(/*@special@*/ poptContext con, int which)
{
/*@-sizeoftype@*/
if (con->arg_strip == NULL)
- con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
+ con->arg_strip = (pbm_set *)PBM_ALLOC(con->optionStack[0].argc);
if (con->arg_strip != NULL) /* XXX can't happen */
PBM_SET(which, con->arg_strip);
/*@=sizeoftype@*/
@@ -738,7 +747,8 @@ int poptGetNextOpt(poptContext con)
/* Make a copy we can hack at */
localOptString = optString =
- strcpy(alloca(strlen(origOptString) + 1), origOptString);
+ strcpy((char *)alloca(strlen(origOptString) + 1),
+ origOptString);
if (optString[0] == '\0')
return POPT_ERROR_BADOPT;
@@ -831,7 +841,7 @@ int poptGetNextOpt(poptContext con)
return POPT_ERROR_BADOPERATION;
}
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
- con->os->nextArg = _free(con->os->nextArg);
+ con->os->nextArg = (const char *)_free(con->os->nextArg);
/*@-usedef@*/ /* FIX: W2DO? */
if (longArg) {
/*@=usedef@*/
@@ -956,12 +966,13 @@ int poptGetNextOpt(poptContext con)
if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
con->finalArgvAlloced += 10;
- con->finalArgv = realloc(con->finalArgv,
+ con->finalArgv = (const char **)realloc(con->finalArgv,
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
if (con->finalArgv != NULL)
- { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
+ { char *s = (char *)malloc(
+ (opt->longName ? strlen(opt->longName) : 0) + 3);
if (s != NULL) { /* XXX can't happen */
if (opt->longName)
sprintf(s, "%s%s",
@@ -1042,47 +1053,47 @@ poptContext poptFreeContext(poptContext con)
if (con == NULL) return con;
poptResetContext(con);
- con->os->argb = _free(con->os->argb);
+ con->os->argb = (pbm_set *)_free(con->os->argb);
if (con->aliases != NULL)
for (i = 0; i < con->numAliases; i++) {
item = con->aliases + i;
/*@-modobserver -observertrans -dependenttrans@*/
- item->option.longName = _free(item->option.longName);
- item->option.descrip = _free(item->option.descrip);
- item->option.argDescrip = _free(item->option.argDescrip);
+ item->option.longName = (const char *)_free(item->option.longName);
+ item->option.descrip = (const char *)_free(item->option.descrip);
+ item->option.argDescrip = (const char *)_free(item->option.argDescrip);
/*@=modobserver =observertrans =dependenttrans@*/
- item->argv = _free(item->argv);
+ item->argv = (const char **)_free(item->argv);
}
- con->aliases = _free(con->aliases);
+ con->aliases = (poptItem)_free(con->aliases);
if (con->execs != NULL)
for (i = 0; i < con->numExecs; i++) {
item = con->execs + i;
/*@-modobserver -observertrans -dependenttrans@*/
- item->option.longName = _free(item->option.longName);
- item->option.descrip = _free(item->option.descrip);
- item->option.argDescrip = _free(item->option.argDescrip);
+ item->option.longName = (const char *)_free(item->option.longName);
+ item->option.descrip = (const char *)_free(item->option.descrip);
+ item->option.argDescrip = (const char *)_free(item->option.argDescrip);
/*@=modobserver =observertrans =dependenttrans@*/
- item->argv = _free(item->argv);
+ item->argv = (const char **)_free(item->argv);
}
- con->execs = _free(con->execs);
-
- con->leftovers = _free(con->leftovers);
- con->finalArgv = _free(con->finalArgv);
- con->appName = _free(con->appName);
- con->otherHelp = _free(con->otherHelp);
- con->execPath = _free(con->execPath);
- con->arg_strip = PBM_FREE(con->arg_strip);
+ con->execs = (poptItem)_free(con->execs);
+
+ con->leftovers = (const char **)_free(con->leftovers);
+ con->finalArgv = (const char **)_free(con->finalArgv);
+ con->appName = (const char *)_free(con->appName);
+ con->otherHelp = (const char *)_free(con->otherHelp);
+ con->execPath = (const char *)_free(con->execPath);
+ con->arg_strip = (pbm_set *)PBM_FREE(con->arg_strip);
- con = _free(con);
+ con = (poptContext)_free(con);
return con;
}
int poptAddAlias(poptContext con, struct poptAlias alias,
/*@unused@*/ int flags)
{
- poptItem item = alloca(sizeof(*item));
+ poptItem item = (poptItem)alloca(sizeof(*item));
memset(item, 0, sizeof(*item));
item->option.longName = alias.longName;
item->option.shortName = alias.shortName;
@@ -1117,7 +1128,7 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
/*@notreached@*/ break;
}
- *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
+ *items = (poptItem)realloc((*items), ((*nitems) + 1) * sizeof(**items));
if ((*items) == NULL)
return 1;
diff --git a/source/printing/notify.c b/source/printing/notify.c
index f27eb2011ff..7d5b7027819 100644
--- a/source/printing/notify.c
+++ b/source/printing/notify.c
@@ -99,7 +99,7 @@ again:
msg->len, msg->notify.data);
if (buflen != len) {
- buf = TALLOC_REALLOC(send_ctx, buf, len);
+ buf = (char *)TALLOC_REALLOC(send_ctx, buf, len);
if (!buf)
return False;
buflen = len;
@@ -140,7 +140,7 @@ static void print_notify_send_messages_to_printer(const char *printer, unsigned
}
offset += 4; /* For count. */
- buf = TALLOC(send_ctx, offset);
+ buf = (char *)TALLOC(send_ctx, offset);
if (!buf) {
DEBUG(0,("print_notify_send_messages: Out of memory\n"));
talloc_free_children(send_ctx);
@@ -220,7 +220,7 @@ static BOOL copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from )
memcpy( to, from, sizeof(SPOOLSS_NOTIFY_MSG) );
if ( from->len ) {
- to->notify.data = TALLOC_MEMDUP(send_ctx, from->notify.data, from->len );
+ to->notify.data = (char *)TALLOC_MEMDUP(send_ctx, from->notify.data, from->len );
if ( !to->notify.data ) {
DEBUG(0,("copy_notify2_msg: talloc_memdup() of size [%d] failed!\n", from->len ));
return False;
@@ -295,7 +295,7 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer));
* the messages are sent in the order they were received. JRA.
*/
- DLIST_ADD_END(notify_queue_head, pnqueue, tmp_ptr);
+ DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *);
num_messages++;
}
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 25633bf4c8f..063e4b3e175 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -385,17 +385,17 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
/* update access masks */
for ( i=0; i<sec->dacl->num_aces; i++ ) {
- switch ( sec->dacl->ace[i].info.mask ) {
+ switch ( sec->dacl->aces[i].access_mask ) {
case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
- sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
+ sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
break;
case GENERIC_ALL_ACCESS:
- sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
+ sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
break;
case READ_CONTROL_ACCESS:
- sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
+ sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
default: /* no change */
break;
@@ -629,14 +629,15 @@ BOOL nt_printing_init(void)
* drivers are installed
*/
- message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
+ message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer, NULL);
/*
* register callback to handle updating printer data
* when a driver is initialized
*/
- message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
+ message_register(MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata,
+ NULL);
/* of course, none of the message callbacks matter if you don't
tell messages.c that you interested in receiving PRINT_GENERAL
@@ -656,13 +657,13 @@ BOOL nt_printing_init(void)
Function to allow filename parsing "the old way".
********************************************************************/
-static BOOL driver_unix_convert(char *name,connection_struct *conn,
- char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
+static void driver_unix_convert(char *name,connection_struct *conn,
+ char *saved_last_component, SMB_STRUCT_STAT *pst)
{
unix_format(name);
unix_clean_name(name);
trim_string(name,"/","/");
- return unix_convert(name, conn, saved_last_component, bad_path, pst);
+ unix_convert(conn, name, False, saved_last_component, pst);
}
/*******************************************************************
@@ -738,6 +739,9 @@ uint32 get_c_setprinter(void)
int get_builtin_ntforms(nt_forms_struct **list)
{
*list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
+ if (!*list) {
+ return 0;
+ }
return sizeof(default_forms) / sizeof(default_forms[0]);
}
@@ -1032,7 +1036,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
char *buf = NULL;
ssize_t byte_count;
- if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
+ if ((buf=(char *)SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
fname, PE_HEADER_SIZE));
goto error_exit;
@@ -1088,7 +1092,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
goto error_exit;
SAFE_FREE(buf);
- if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
+ if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
fname, section_table_bytes));
goto error_exit;
@@ -1112,7 +1116,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
goto error_exit;
SAFE_FREE(buf);
- if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
+ if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
fname, section_bytes));
goto error_exit;
@@ -1172,7 +1176,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
/* Allocate a bit more space to speed up things */
SAFE_FREE(buf);
- if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
+ if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
fname, PE_HEADER_SIZE));
goto error_exit;
@@ -1276,7 +1280,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
SMB_STRUCT_STAT stat_buf;
- BOOL bad_path;
+
+ NTSTATUS status;
SET_STAT_INVALID(st);
SET_STAT_INVALID(stat_buf);
@@ -1286,18 +1291,18 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
/* Get file version info (if available) for previous file (if it exists) */
pstrcpy(filepath, old_file);
- driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+ driver_unix_convert(filepath,conn,NULL,&stat_buf);
- fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+ status = open_file_ntcreate(conn, filepath, &stat_buf,
FILE_GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
INTERNAL_OPEN_ONLY,
- NULL);
+ NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
/* Old file not found, so by definition new file is in fact newer */
DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
filepath, errno));
@@ -1322,18 +1327,18 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
/* Get file version info (if available) for new file */
pstrcpy(filepath, new_file);
- driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+ driver_unix_convert(filepath,conn,NULL,&stat_buf);
- fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+ status = open_file_ntcreate(conn, filepath, &stat_buf,
FILE_GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
INTERNAL_OPEN_ONLY,
- NULL);
+ NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
/* New file not found, this shouldn't occur if the caller did its job */
DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
filepath, errno));
@@ -1399,9 +1404,9 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
DATA_BLOB null_pw;
fstring res_type;
files_struct *fsp = NULL;
- BOOL bad_path;
SMB_STRUCT_STAT st;
connection_struct *conn;
+ NTSTATUS status;
SET_STAT_INVALID(st);
@@ -1450,23 +1455,23 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
* deriver the cversion. */
slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
- driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
+ driver_unix_convert(driverpath,conn,NULL,&st);
if ( !vfs_file_exist( conn, driverpath, &st ) ) {
*perr = WERR_BADFILE;
goto error_exit;
}
- fsp = open_file_ntcreate(conn, driverpath, &st,
+ status = open_file_ntcreate(conn, driverpath, &st,
FILE_GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
INTERNAL_OPEN_ONLY,
- NULL);
+ NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
driverpath, errno));
*perr = WERR_ACCESS_DENIED;
@@ -1736,11 +1741,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
pstring inbuf;
pstring outbuf;
fstring res_type;
- BOOL bad_path;
SMB_STRUCT_STAT st;
int ver = 0;
int i;
- int err;
memset(inbuf, '\0', sizeof(inbuf));
memset(outbuf, '\0', sizeof(outbuf));
@@ -1793,8 +1796,8 @@ WERROR 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, bad_path);
+ driver_unix_convert(new_dir, conn, NULL, &st);
+ create_directory(conn, new_dir);
/* 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:
@@ -1819,9 +1822,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+ driver_unix_convert(new_name, conn, NULL, &st);
+ if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
*perr = WERR_ACCESS_DENIED;
@@ -1835,9 +1838,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+ driver_unix_convert(new_name, conn, NULL, &st);
+ if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
*perr = WERR_ACCESS_DENIED;
@@ -1853,9 +1856,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+ driver_unix_convert(new_name, conn, NULL, &st);
+ if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
*perr = WERR_ACCESS_DENIED;
@@ -1872,9 +1875,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+ driver_unix_convert(new_name, conn, NULL, &st);
+ if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
*perr = WERR_ACCESS_DENIED;
@@ -1900,10 +1903,10 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
- if ( !copy_file(new_name, old_name, conn,
+ driver_unix_convert(new_name, conn, NULL, &st);
+ if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn,
OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+ OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
*perr = WERR_ACCESS_DENIED;
@@ -2077,7 +2080,11 @@ static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **in
memset(info.dependentfiles, '\0', 2*sizeof(fstring));
fstrcpy(info.dependentfiles[0], "");
- *info_ptr = memdup(&info, sizeof(info));
+ *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
+ if (!*info_ptr) {
+ SAFE_FREE(info.dependentfiles);
+ return WERR_NOMEM;
+ }
return WERR_OK;
}
@@ -2152,6 +2159,10 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
}
*info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
+ if (!*info_ptr) {
+ SAFE_FREE(driver.dependentfiles);
+ return WERR_NOMEM;
+ }
return WERR_OK;
}
@@ -2541,7 +2552,7 @@ NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
new_nt_devicemode->nt_dev_private = NULL;
if (nt_devicemode->nt_dev_private != NULL) {
- if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
+ if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
SAFE_FREE(new_nt_devicemode);
DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
return NULL;
@@ -2652,6 +2663,10 @@ int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
}
*nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
+ if (!*nt_devmode) {
+ SAFE_FREE(devmode.nt_dev_private);
+ return -1;
+ }
DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
if (devmode.nt_dev_private)
@@ -2984,11 +2999,15 @@ static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
return True;
}
+/*****************************************************************
+ ****************************************************************/
+
static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
- struct uuid guid)
+ struct GUID guid)
{
int i;
REGVAL_CTR *ctr=NULL;
+ UNISTR2 unistr_guid;
/* find the DsSpooler key */
if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
@@ -2996,21 +3015,31 @@ static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
ctr = info2->data->keys[i].values;
regval_ctr_delvalue(ctr, "objectGUID");
- regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
- (char *) &guid, sizeof(struct uuid));
+
+ /* We used to store this as a REG_BINARY but that causes
+ Vista to whine */
+
+ ZERO_STRUCT( unistr_guid );
+ init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
+ UNI_STR_TERMINATE );
+
+ regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
+ (char *)unistr_guid.buffer,
+ unistr_guid.uni_max_len*2);
+
}
static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
NT_PRINTER_INFO_LEVEL *printer)
{
ADS_STATUS ads_rc;
- void *res;
+ LDAPMessage *res;
char *prt_dn = NULL, *srv_dn, *srv_cn_0;
char *srv_dn_utf8, **srv_cn_utf8;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
const char *attrs[] = {"objectGUID", NULL};
- struct uuid guid;
+ struct GUID guid;
WERROR win_rc = WERR_OK;
DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
@@ -3021,7 +3050,7 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
/* We use ldap_get_dn here as we need the answer
* in utf8 to call ldap_explode_dn(). JRA. */
- srv_dn_utf8 = ldap_get_dn(ads->ld, res);
+ srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
if (!srv_dn_utf8) {
ads_destroy(&ads);
return WERR_SERVER_UNAVAILABLE;
@@ -3103,7 +3132,7 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
NT_PRINTER_INFO_LEVEL *printer)
{
ADS_STATUS ads_rc;
- void *res;
+ LDAPMessage *res;
char *prt_dn = NULL;
DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
@@ -3247,13 +3276,14 @@ WERROR check_published_printers(void)
}
BOOL is_printer_published(Printer_entry *print_hnd, int snum,
- struct uuid *guid)
+ struct GUID *guid)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
REGVAL_CTR *ctr;
REGISTRY_VALUE *guid_val;
WERROR win_rc;
int i;
+ BOOL ret = False;
win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
@@ -3267,12 +3297,36 @@ BOOL is_printer_published(Printer_entry *print_hnd, int snum,
return False;
}
- /* fetching printer guids really ought to be a separate function.. */
- if (guid && regval_size(guid_val) == sizeof(struct uuid))
- memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
+ /* fetching printer guids really ought to be a separate function. */
+
+ if ( guid ) {
+ fstring guid_str;
+
+ /* We used to store the guid as REG_BINARY, then swapped
+ to REG_SZ for Vista compatibility so check for both */
+
+ switch ( regval_type(guid_val) ){
+ case REG_SZ:
+ rpcstr_pull( guid_str, regval_data_p(guid_val),
+ sizeof(guid_str)-1, -1, STR_TERMINATE );
+ ret = smb_string_to_uuid( guid_str, guid );
+ break;
+ case REG_BINARY:
+ if ( regval_size(guid_val) != sizeof(struct GUID) ) {
+ ret = False;
+ break;
+ }
+ memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
+ break;
+ default:
+ DEBUG(0,("is_printer_published: GUID value stored as "
+ "invaluid type (%d)\n", regval_type(guid_val) ));
+ break;
+ }
+ }
free_a_printer(&printer, 2);
- return True;
+ return ret;
}
#else
WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
@@ -3286,7 +3340,7 @@ WERROR check_published_printers(void)
}
BOOL is_printer_published(Printer_entry *print_hnd, int snum,
- struct uuid *guid)
+ struct GUID *guid)
{
return False;
}
@@ -3539,13 +3593,43 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
break;
}
- /* add the new value */
+ DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
+
+ /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
+ Thanks to Martin Zielinski for the hint. */
+
+ if ( type == REG_BINARY &&
+ strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
+ strequal( valuename, "objectGUID" ) )
+ {
+ struct GUID guid;
+ UNISTR2 unistr_guid;
+
+ ZERO_STRUCT( unistr_guid );
+
+ /* convert the GUID to a UNICODE string */
+
+ memcpy( &guid, data_p, sizeof(struct GUID) );
+
+ init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
+ UNI_STR_TERMINATE );
+
+ regval_ctr_addvalue( printer_data->keys[key_index].values,
+ valuename, REG_SZ,
+ (const char *)unistr_guid.buffer,
+ unistr_guid.uni_str_len*2 );
+
+ } else {
+ /* add the value */
+
+ regval_ctr_addvalue( printer_data->keys[key_index].values,
+ valuename, type, (const char *)data_p,
+ size );
+ }
- regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
- DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
}
return len;
@@ -4353,7 +4437,8 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print
fstrcpy( servername, print_hnd->servername );
else {
fstrcpy( servername, "%L" );
- standard_sub_basic( "", servername, sizeof(servername)-1 );
+ standard_sub_basic( "", "", servername,
+ sizeof(servername)-1 );
}
result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
@@ -4794,7 +4879,6 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
DATA_BLOB null_pw;
NTSTATUS nt_status;
fstring res_type;
- BOOL bad_path;
SMB_STRUCT_STAT st;
if ( !info_3 )
@@ -4837,7 +4921,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->driverpath ) {
if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting driverfile [%s]\n", s));
unlink_internals(conn, 0, file, False, False);
}
@@ -4846,7 +4930,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->configfile ) {
if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting configfile [%s]\n", s));
unlink_internals(conn, 0, file, False, False);
}
@@ -4855,7 +4939,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->datafile ) {
if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting datafile [%s]\n", s));
unlink_internals(conn, 0, file, False, False);
}
@@ -4864,7 +4948,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( *info_3->helpfile ) {
if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
pstrcpy( file, s );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting helpfile [%s]\n", s));
unlink_internals(conn, 0, file, False, False);
}
@@ -4880,7 +4964,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
pstrcpy( file, p );
- driver_unix_convert(file, conn, NULL, &bad_path, &st);
+ driver_unix_convert(file, conn, NULL, &st);
DEBUG(10,("deleting dependent file [%s]\n", file));
unlink_internals(conn, 0, file, False, False);
}
@@ -4979,7 +5063,7 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
permissions through NT. If they are NULL in the new security
descriptor then copy them over from the old one. */
- if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
+ if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->group_sid) {
DOM_SID *owner_sid, *group_sid;
SEC_ACL *dacl, *sacl;
SEC_DESC *psd = NULL;
@@ -4996,9 +5080,9 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
secdesc_ctr->sec->owner_sid :
old_secdesc_ctr->sec->owner_sid;
- group_sid = secdesc_ctr->sec->grp_sid ?
- secdesc_ctr->sec->grp_sid :
- old_secdesc_ctr->sec->grp_sid;
+ group_sid = secdesc_ctr->sec->group_sid ?
+ secdesc_ctr->sec->group_sid :
+ old_secdesc_ctr->sec->group_sid;
dacl = secdesc_ctr->sec->dacl ?
secdesc_ctr->sec->dacl :
@@ -5209,7 +5293,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s
psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
&owner_sid,
- (*secdesc_ctr)->sec->grp_sid,
+ (*secdesc_ctr)->sec->group_sid,
(*secdesc_ctr)->sec->sacl,
(*secdesc_ctr)->sec->dacl,
&size);
@@ -5243,11 +5327,11 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s
for (i = 0; i < the_acl->num_aces; i++) {
fstring sid_str;
- sid_to_string(sid_str, &the_acl->ace[i].trustee);
+ sid_to_string(sid_str, &the_acl->aces[i].trustee);
DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
- the_acl->ace[i].type, the_acl->ace[i].flags,
- the_acl->ace[i].info.mask));
+ the_acl->aces[i].type, the_acl->aces[i].flags,
+ the_acl->aces[i].access_mask));
}
}
@@ -5299,7 +5383,7 @@ void map_printer_permissions(SEC_DESC *sd)
int i;
for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
- se_map_generic(&sd->dacl->ace[i].info.mask,
+ se_map_generic(&sd->dacl->aces[i].access_mask,
&printer_generic_mapping);
}
}
@@ -5426,7 +5510,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
Check the time parameters allow a print operation.
*****************************************************************************/
-BOOL print_time_access_check(int snum)
+BOOL print_time_access_check(const char *servicename)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
BOOL ok = False;
@@ -5434,7 +5518,7 @@ BOOL print_time_access_check(int snum)
struct tm *t;
uint32 mins;
- if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
+ if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
return False;
if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c
index afa301bbea1..2c942627c6b 100644
--- a/source/printing/print_cups.c
+++ b/source/printing/print_cups.c
@@ -25,6 +25,7 @@
#include <cups/cups.h>
#include <cups/language.h>
+extern userdom_struct current_user_info;
/*
* 'cups_passwd_cb()' - The CUPS password callback...
@@ -40,16 +41,38 @@ cups_passwd_cb(const char *prompt) /* I - Prompt */
return (NULL);
}
-static const char *cups_server(void)
+static http_t *cups_connect(void)
{
- if ((lp_cups_server() != NULL) && (strlen(lp_cups_server()) > 0)) {
- DEBUG(10, ("cups server explicitly set to %s\n",
- lp_cups_server()));
- return lp_cups_server();
+ http_t *http;
+ char *server, *p;
+ int port;
+
+ if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
+ server = smb_xstrdup(lp_cups_server());
+ } else {
+ server = smb_xstrdup(cupsServer());
+ }
+
+ p = strchr(server, ':');
+ if (p) {
+ port = atoi(p+1);
+ *p = '\0';
+ } else {
+ port = ippPort();
+ }
+
+ DEBUG(10, ("connecting to cups server %s:%d\n",
+ server, port));
+
+ if ((http = httpConnect(server, port)) == NULL) {
+ DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
+ server, port, strerror(errno)));
+ SAFE_FREE(server);
+ return NULL;
}
- DEBUG(10, ("cups server left to default %s\n", cupsServer()));
- return cupsServer();
+ SAFE_FREE(server);
+ return http;
}
BOOL cups_cache_reload(void)
@@ -80,9 +103,7 @@ BOOL cups_cache_reload(void)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -287,9 +308,7 @@ static int cups_job_delete(const char *sharename, const char *lprm_command, stru
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -379,9 +398,7 @@ static int cups_job_pause(int snum, struct printjob *pjob)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -471,9 +488,7 @@ static int cups_job_resume(int snum, struct printjob *pjob)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -566,9 +581,7 @@ static int cups_job_submit(int snum, struct printjob *pjob)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -732,9 +745,7 @@ static int cups_queue_get(const char *sharename,
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -996,7 +1007,6 @@ static int cups_queue_get(const char *sharename,
static int cups_queue_pause(int snum)
{
- extern userdom_struct current_user_info;
int ret = 1; /* Return value */
http_t *http = NULL; /* HTTP connection to server */
ipp_t *request = NULL, /* IPP Request */
@@ -1017,9 +1027,7 @@ static int cups_queue_pause(int snum)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -1090,7 +1098,6 @@ static int cups_queue_pause(int snum)
static int cups_queue_resume(int snum)
{
- extern userdom_struct current_user_info;
int ret = 1; /* Return value */
http_t *http = NULL; /* HTTP connection to server */
ipp_t *request = NULL, /* IPP Request */
@@ -1111,9 +1118,7 @@ static int cups_queue_resume(int snum)
* Try to connect to the server...
*/
- if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
- DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
- cups_server(), strerror(errno)));
+ if ((http = cups_connect()) == NULL) {
goto out;
}
@@ -1195,5 +1200,6 @@ struct printif cups_printif =
#else
/* this keeps fussy compilers happy */
+ void print_cups_dummy(void);
void print_cups_dummy(void) {}
#endif /* HAVE_CUPS */
diff --git a/source/printing/print_generic.c b/source/printing/print_generic.c
index 1ea762695b1..1e55f712c53 100644
--- a/source/printing/print_generic.c
+++ b/source/printing/print_generic.c
@@ -21,6 +21,8 @@
#include "includes.h"
#include "printing.h"
+extern struct current_user current_user;
+extern userdom_struct current_user_info;
/****************************************************************************
run a given print command
@@ -30,7 +32,6 @@ for local substitution strings
static int print_run_command(int snum, const char* printername, BOOL do_sub,
const char *command, int *outfd, ...)
{
-
pstring syscmd;
char *arg;
int ret;
@@ -56,7 +57,12 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub,
pstring_sub( syscmd, "%p", printername );
if ( do_sub && snum != -1 )
- standard_sub_snum(snum,syscmd,sizeof(syscmd));
+ standard_sub_advanced(lp_servicename(snum),
+ current_user_info.unix_name, "",
+ current_user.ut.gid,
+ get_current_username(),
+ current_user_info.domain,
+ syscmd, sizeof(syscmd));
ret = smbrun(syscmd,outfd);
diff --git a/source/printing/print_iprint.c b/source/printing/print_iprint.c
index 04b096a8a5b..29cb69087fa 100644
--- a/source/printing/print_iprint.c
+++ b/source/printing/print_iprint.c
@@ -92,7 +92,7 @@ static int iprint_get_server_version(http_t *http, char* serviceUri)
request = ippNew();
- request->request.op.operation_id = OPERATION_NOVELL_MGMT;
+ request->request.op.operation_id = (ipp_op_t)OPERATION_NOVELL_MGMT;
request->request.op.request_id = 1;
language = cupsLangDefault();
@@ -343,7 +343,8 @@ BOOL iprint_cache_reload(void)
request = ippNew();
- request->request.op.operation_id = OPERATION_NOVELL_LIST_PRINTERS;
+ request->request.op.operation_id =
+ (ipp_op_t)OPERATION_NOVELL_LIST_PRINTERS;
request->request.op.request_id = 1;
language = cupsLangDefault();
@@ -1234,5 +1235,6 @@ struct printif iprint_printif =
#else
/* this keeps fussy compilers happy */
+ void print_iprint_dummy(void);
void print_iprint_dummy(void) {}
#endif /* HAVE_IPRINT */
diff --git a/source/printing/print_test.c b/source/printing/print_test.c
new file mode 100644
index 00000000000..b26b1356774
--- /dev/null
+++ b/source/printing/print_test.c
@@ -0,0 +1,82 @@
+/*
+ * Printing backend for the build farm
+ *
+ * Copyright (C) Volker Lendecke 2006
+ *
+ * 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 "printing.h"
+
+#if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
+
+static int test_queue_get(const char *printer_name,
+ enum printing_types printing_type,
+ char *lpq_command,
+ print_queue_struct **q,
+ print_status_struct *status)
+{
+ return -1;
+}
+
+static int test_queue_pause(int snum)
+{
+ return -1;
+}
+
+static int test_queue_resume(int snum)
+{
+ return -1;
+}
+
+static int test_job_delete(const char *sharename, const char *lprm_command,
+ struct printjob *pjob)
+{
+ return -1;
+}
+
+static int test_job_pause(int snum, struct printjob *pjob)
+{
+ return -1;
+}
+
+static int test_job_resume(int snum, struct printjob *pjob)
+{
+ return -1;
+}
+
+static int test_job_submit(int snum, struct printjob *pjob)
+{
+ return -1;
+};
+
+struct printif test_printif =
+{
+ PRINT_TEST,
+ test_queue_get,
+ test_queue_pause,
+ test_queue_resume,
+ test_job_delete,
+ test_job_pause,
+ test_job_resume,
+ test_job_submit,
+};
+
+#else
+ /* this keeps fussy compilers happy */
+ void print_test_dummy(void);
+ void print_test_dummy(void) {}
+#endif /* DEVELOPER||ENABLE_BUILD_FARM_HACKS */
diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c
index c248851822b..5278c60f992 100644
--- a/source/printing/printfsp.c
+++ b/source/printing/printfsp.c
@@ -28,15 +28,19 @@ open a print file and setup a fsp for it. This is a wrapper around
print_job_start().
***************************************************************************/
-files_struct *print_fsp_open(connection_struct *conn, const char *fname)
+NTSTATUS print_fsp_open(connection_struct *conn, const char *fname,
+ files_struct **result)
{
int jobid;
SMB_STRUCT_STAT sbuf;
- files_struct *fsp = file_new(conn);
+ files_struct *fsp;
fstring name;
+ NTSTATUS status;
- if(!fsp)
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
fstrcpy( name, "Remote Downlevel Document");
if (fname) {
@@ -50,8 +54,9 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
jobid = print_job_start(&current_user, SNUM(conn), name, NULL);
if (jobid == -1) {
+ status = map_nt_error_from_unix(errno);
file_free(fsp);
- return NULL;
+ return status;
}
/* Convert to RAP id. */
@@ -60,7 +65,7 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
/* We need to delete the entry in the tdb. */
pjob_delete(lp_const_servicename(SNUM(conn)), jobid);
file_free(fsp);
- return NULL;
+ return NT_STATUS_ACCESS_DENIED; /* No errno around here */
}
/* setup a full fsp */
@@ -87,7 +92,8 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
conn->num_files_open++;
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
}
/****************************************************************************
diff --git a/source/printing/printing.c b/source/printing/printing.c
index 9dd6bec0be4..39efe19604e 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -25,6 +25,8 @@
extern SIG_ATOMIC_T got_sig_term;
extern SIG_ATOMIC_T reload_after_sighup;
+extern struct current_user current_user;
+extern userdom_struct current_user_info;
/* Current printer interface */
static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid);
@@ -271,7 +273,7 @@ static TDB_DATA print_key(uint32 jobid)
TDB_DATA ret;
SIVAL(&j, 0, jobid);
- ret.dptr = (void *)&j;
+ ret.dptr = (char *)&j;
ret.dsize = sizeof(j);
return ret;
}
@@ -839,10 +841,9 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
Check if the print queue has been updated recently enough.
****************************************************************************/
-static void print_cache_flush(int snum)
+static void print_cache_flush(const char *sharename)
{
fstring key;
- const char *sharename = lp_const_servicename(snum);
struct tdb_print_db *pdb = get_print_db_byname(sharename);
if (!pdb)
@@ -918,7 +919,7 @@ static void set_updating_pid(const fstring sharename, BOOL updating)
}
SIVAL( buffer, 0, updating_pid);
- data.dptr = (void *)buffer;
+ data.dptr = (char *)buffer;
data.dsize = 4; /* we always assume this is a 4 byte value */
tdb_store(pdb->tdb, key, data, TDB_REPLACE);
@@ -985,7 +986,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
queue[i].fs_file);
}
- if ((data.dptr = SMB_MALLOC(data.dsize)) == NULL)
+ if ((data.dptr = (char *)SMB_MALLOC(data.dsize)) == NULL)
return;
len = 0;
@@ -1236,7 +1237,7 @@ static void print_queue_update_internal( const char *sharename,
key.dsize = strlen(keystr);
status.qcount = qcount;
- data.dptr = (void *)&status;
+ data.dptr = (char *)&status;
data.dsize = sizeof(status);
tdb_store(pdb->tdb, key, data, TDB_REPLACE);
@@ -1351,14 +1352,15 @@ static void print_queue_update_with_lock( const char *sharename,
this is the receive function of the background lpq updater
****************************************************************************/
static void print_queue_receive(int msg_type, struct process_id src,
- void *buf, size_t msglen)
+ void *buf, size_t msglen,
+ void *private_data)
{
fstring sharename;
pstring lpqcommand, lprmcommand;
int printing_type;
size_t len;
- len = tdb_unpack( buf, msglen, "fdPP",
+ len = tdb_unpack( (char *)buf, msglen, "fdPP",
sharename,
&printing_type,
lpqcommand,
@@ -1402,7 +1404,8 @@ void start_background_queue(void)
exit(1);
}
- message_register(MSG_PRINTER_UPDATE, print_queue_receive);
+ message_register(MSG_PRINTER_UPDATE, print_queue_receive,
+ NULL);
DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
while (1) {
@@ -1456,12 +1459,22 @@ static void print_queue_update(int snum, BOOL force)
pstrcpy( lpqcommand, lp_lpqcommand(snum));
string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand),
False, False, False );
- standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
+ standard_sub_advanced(lp_servicename(snum),
+ current_user_info.unix_name, "",
+ current_user.ut.gid,
+ get_current_username(),
+ current_user_info.domain,
+ lpqcommand, sizeof(lpqcommand) );
pstrcpy( lprmcommand, lp_lprmcommand(snum));
string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand),
False, False, False );
- standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) );
+ standard_sub_advanced(lp_servicename(snum),
+ current_user_info.unix_name, "",
+ current_user.ut.gid,
+ get_current_username(),
+ current_user_info.domain,
+ lprmcommand, sizeof(lprmcommand) );
/*
* Make sure that the background queue process exists.
@@ -1524,10 +1537,8 @@ static void print_queue_update(int snum, BOOL force)
/* finally send the message */
- become_root();
message_send_pid(pid_to_procid(background_lpq_updater_pid),
MSG_PRINTER_UPDATE, buffer, len, False);
- unbecome_root();
SAFE_FREE( buffer );
@@ -1596,7 +1607,7 @@ BOOL print_notify_register_pid(int snum)
if (i == data.dsize) {
/* We weren't in the list. Realloc. */
- data.dptr = SMB_REALLOC(data.dptr, data.dsize + 8);
+ data.dptr = (char *)SMB_REALLOC(data.dptr, data.dsize + 8);
if (!data.dptr) {
DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
printername));
@@ -1781,7 +1792,7 @@ NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
Set the place in the queue for a job.
****************************************************************************/
-BOOL print_job_set_place(int snum, uint32 jobid, int place)
+BOOL print_job_set_place(const char *sharename, uint32 jobid, int place)
{
DEBUG(2,("print_job_set_place not implemented yet\n"));
return False;
@@ -1791,9 +1802,8 @@ BOOL print_job_set_place(int snum, uint32 jobid, int place)
Set the name of a job. Only possible for owner.
****************************************************************************/
-BOOL print_job_set_name(int snum, uint32 jobid, char *name)
+BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name)
{
- const char* sharename = lp_const_servicename(snum);
struct printjob *pjob;
pjob = print_job_find(sharename, jobid);
@@ -1930,9 +1940,10 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
Return true if the current user owns the print job.
****************************************************************************/
-static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
+static BOOL is_owner(struct current_user *user, const char *servicename,
+ uint32 jobid)
{
- struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid);
+ struct printjob *pjob = print_job_find(servicename, jobid);
user_struct *vuser;
if (!pjob || !user)
@@ -1958,7 +1969,7 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR
*errcode = WERR_OK;
- owner = is_owner(user, snum, jobid);
+ owner = is_owner(user, lp_const_servicename(snum), jobid);
/* Check access against security descriptor or whether the user
owns their job. */
@@ -2037,7 +2048,7 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *
return False;
}
- if (!is_owner(user, snum, jobid) &&
+ if (!is_owner(user, lp_const_servicename(snum), jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("pause denied by security descriptor\n"));
@@ -2061,7 +2072,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
}
/* force update the database */
- print_cache_flush(snum);
+ print_cache_flush(lp_const_servicename(snum));
/* Send a printer notify message */
@@ -2097,7 +2108,7 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
return False;
}
- if (!is_owner(user, snum, jobid) &&
+ if (!is_owner(user, lp_const_servicename(snum), jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("resume denied by security descriptor\n"));
*errcode = WERR_ACCESS_DENIED;
@@ -2119,7 +2130,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
}
/* force update the database */
- print_cache_flush(snum);
+ print_cache_flush(lp_const_servicename(snum));
/* Send a printer notify message */
@@ -2325,7 +2336,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
return (uint32)-1;
}
- if (!print_time_access_check(snum)) {
+ if (!print_time_access_check(lp_servicename(snum))) {
DEBUG(3, ("print_job_start: job start denied by time check\n"));
release_print_db(pdb);
return (uint32)-1;
@@ -2385,7 +2396,11 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
fstrcpy(pjob.jobname, jobname);
if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
- fstrcpy(pjob.user, vuser->user.smb_name);
+ fstrcpy(pjob.user, lp_printjob_username(snum));
+ standard_sub_basic(vuser->user.smb_name, vuser->user.domain,
+ pjob.user, sizeof(pjob.user)-1);
+ /* ensure NULL termination */
+ pjob.user[sizeof(pjob.user)-1] = '\0';
} else {
fstrcpy(pjob.user, uidtoname(user->ut.uid));
}
@@ -2739,7 +2754,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
}
/* force update the database */
- print_cache_flush(snum);
+ print_cache_flush(lp_const_servicename(snum));
/* Send a printer notify message */
@@ -2805,7 +2820,7 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
become_root();
for (i=0;i<njobs;i++) {
- BOOL owner = is_owner(user, snum, queue[i].job);
+ BOOL owner = is_owner(user, lp_const_servicename(snum), queue[i].job);
if (owner || can_job_admin) {
print_job_delete1(snum, queue[i].job);
diff --git a/source/profile/profile.c b/source/profile/profile.c
index c3512ec01d8..4568678739f 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -2,7 +2,8 @@
Unix SMB/CIFS implementation.
store smbd profiling information in shared memory
Copyright (C) Andrew Tridgell 1999
-
+ Copyright (C) James Peach 2006
+
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
@@ -43,7 +44,7 @@ BOOL do_profile_times = False;
/****************************************************************************
receive a set profile level message
****************************************************************************/
-void profile_message(int msg_type, struct process_id src, void *buf, size_t len)
+void profile_message(int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
{
int level;
@@ -96,7 +97,7 @@ void profile_message(int msg_type, struct process_id src, void *buf, size_t len)
receive a request profile level message
****************************************************************************/
void reqprofile_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
int level;
@@ -228,7 +229,7 @@ BOOL profile_setup(BOOL rdonly)
}
if (shm_ds.shm_segsz != sizeof(*profile_h)) {
- DEBUG(0,("WARNING: profile size is %d (expected %d). Deleting\n",
+ DEBUG(0,("WARNING: profile size is %d (expected %lu). Deleting\n",
(int)shm_ds.shm_segsz, sizeof(*profile_h)));
if (shmctl(shm_id, IPC_RMID, &shm_ds) == 0) {
goto again;
@@ -245,8 +246,188 @@ BOOL profile_setup(BOOL rdonly)
}
profile_p = &profile_h->stats;
- message_register(MSG_PROFILE, profile_message);
- message_register(MSG_REQ_PROFILELEVEL, reqprofile_message);
+ message_register(MSG_PROFILE, profile_message, NULL);
+ message_register(MSG_REQ_PROFILELEVEL, reqprofile_message, NULL);
return True;
}
+
+ const char * profile_value_name(enum profile_stats_values val)
+{
+ static const char * valnames[PR_VALUE_MAX + 1] =
+ {
+ "smbd_idle", /* PR_VALUE_SMBD_IDLE */
+ "syscall_opendir", /* PR_VALUE_SYSCALL_OPENDIR */
+ "syscall_readdir", /* PR_VALUE_SYSCALL_READDIR */
+ "syscall_seekdir", /* PR_VALUE_SYSCALL_SEEKDIR */
+ "syscall_telldir", /* PR_VALUE_SYSCALL_TELLDIR */
+ "syscall_rewinddir", /* PR_VALUE_SYSCALL_REWINDDIR */
+ "syscall_mkdir", /* PR_VALUE_SYSCALL_MKDIR */
+ "syscall_rmdir", /* PR_VALUE_SYSCALL_RMDIR */
+ "syscall_closedir", /* PR_VALUE_SYSCALL_CLOSEDIR */
+ "syscall_open", /* PR_VALUE_SYSCALL_OPEN */
+ "syscall_close", /* PR_VALUE_SYSCALL_CLOSE */
+ "syscall_read", /* PR_VALUE_SYSCALL_READ */
+ "syscall_pread", /* PR_VALUE_SYSCALL_PREAD */
+ "syscall_write", /* PR_VALUE_SYSCALL_WRITE */
+ "syscall_pwrite", /* PR_VALUE_SYSCALL_PWRITE */
+ "syscall_lseek", /* PR_VALUE_SYSCALL_LSEEK */
+ "syscall_sendfile", /* PR_VALUE_SYSCALL_SENDFILE */
+ "syscall_rename", /* PR_VALUE_SYSCALL_RENAME */
+ "syscall_fsync", /* PR_VALUE_SYSCALL_FSYNC */
+ "syscall_stat", /* PR_VALUE_SYSCALL_STAT */
+ "syscall_fstat", /* PR_VALUE_SYSCALL_FSTAT */
+ "syscall_lstat", /* PR_VALUE_SYSCALL_LSTAT */
+ "syscall_unlink", /* PR_VALUE_SYSCALL_UNLINK */
+ "syscall_chmod", /* PR_VALUE_SYSCALL_CHMOD */
+ "syscall_fchmod", /* PR_VALUE_SYSCALL_FCHMOD */
+ "syscall_chown", /* PR_VALUE_SYSCALL_CHOWN */
+ "syscall_fchown", /* PR_VALUE_SYSCALL_FCHOWN */
+ "syscall_chdir", /* PR_VALUE_SYSCALL_CHDIR */
+ "syscall_getwd", /* PR_VALUE_SYSCALL_GETWD */
+ "syscall_utime", /* PR_VALUE_SYSCALL_UTIME */
+ "syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */
+ "syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */
+ "syscall_kernel_flock", /* PR_VALUE_SYSCALL_KERNEL_FLOCK */
+ "syscall_linux_setlease", /* PR_VALUE_SYSCALL_LINUX_SETLEASE */
+ "syscall_fcntl_getlock", /* PR_VALUE_SYSCALL_FCNTL_GETLOCK */
+ "syscall_readlink", /* PR_VALUE_SYSCALL_READLINK */
+ "syscall_symlink", /* PR_VALUE_SYSCALL_SYMLINK */
+ "syscall_link", /* PR_VALUE_SYSCALL_LINK */
+ "syscall_mknod", /* PR_VALUE_SYSCALL_MKNOD */
+ "syscall_realpath", /* PR_VALUE_SYSCALL_REALPATH */
+ "syscall_get_quota", /* PR_VALUE_SYSCALL_GET_QUOTA */
+ "syscall_set_quota", /* PR_VALUE_SYSCALL_SET_QUOTA */
+ "SMBmkdir", /* PR_VALUE_SMBMKDIR */
+ "SMBrmdir", /* PR_VALUE_SMBRMDIR */
+ "SMBopen", /* PR_VALUE_SMBOPEN */
+ "SMBcreate", /* PR_VALUE_SMBCREATE */
+ "SMBclose", /* PR_VALUE_SMBCLOSE */
+ "SMBflush", /* PR_VALUE_SMBFLUSH */
+ "SMBunlink", /* PR_VALUE_SMBUNLINK */
+ "SMBmv", /* PR_VALUE_SMBMV */
+ "SMBgetatr", /* PR_VALUE_SMBGETATR */
+ "SMBsetatr", /* PR_VALUE_SMBSETATR */
+ "SMBread", /* PR_VALUE_SMBREAD */
+ "SMBwrite", /* PR_VALUE_SMBWRITE */
+ "SMBlock", /* PR_VALUE_SMBLOCK */
+ "SMBunlock", /* PR_VALUE_SMBUNLOCK */
+ "SMBctemp", /* PR_VALUE_SMBCTEMP */
+ "SMBmknew", /* PR_VALUE_SMBMKNEW */
+ "SMBcheckpath", /* PR_VALUE_SMBCHECKPATH */
+ "SMBexit", /* PR_VALUE_SMBEXIT */
+ "SMBlseek", /* PR_VALUE_SMBLSEEK */
+ "SMBlockread", /* PR_VALUE_SMBLOCKREAD */
+ "SMBwriteunlock", /* PR_VALUE_SMBWRITEUNLOCK */
+ "SMBreadbraw", /* PR_VALUE_SMBREADBRAW */
+ "SMBreadBmpx", /* PR_VALUE_SMBREADBMPX */
+ "SMBreadBs", /* PR_VALUE_SMBREADBS */
+ "SMBwritebraw", /* PR_VALUE_SMBWRITEBRAW */
+ "SMBwriteBmpx", /* PR_VALUE_SMBWRITEBMPX */
+ "SMBwriteBs", /* PR_VALUE_SMBWRITEBS */
+ "SMBwritec", /* PR_VALUE_SMBWRITEC */
+ "SMBsetattrE", /* PR_VALUE_SMBSETATTRE */
+ "SMBgetattrE", /* PR_VALUE_SMBGETATTRE */
+ "SMBlockingX", /* PR_VALUE_SMBLOCKINGX */
+ "SMBtrans", /* PR_VALUE_SMBTRANS */
+ "SMBtranss", /* PR_VALUE_SMBTRANSS */
+ "SMBioctl", /* PR_VALUE_SMBIOCTL */
+ "SMBioctls", /* PR_VALUE_SMBIOCTLS */
+ "SMBcopy", /* PR_VALUE_SMBCOPY */
+ "SMBmove", /* PR_VALUE_SMBMOVE */
+ "SMBecho", /* PR_VALUE_SMBECHO */
+ "SMBwriteclose", /* PR_VALUE_SMBWRITECLOSE */
+ "SMBopenX", /* PR_VALUE_SMBOPENX */
+ "SMBreadX", /* PR_VALUE_SMBREADX */
+ "SMBwriteX", /* PR_VALUE_SMBWRITEX */
+ "SMBtrans2", /* PR_VALUE_SMBTRANS2 */
+ "SMBtranss2", /* PR_VALUE_SMBTRANSS2 */
+ "SMBfindclose", /* PR_VALUE_SMBFINDCLOSE */
+ "SMBfindnclose", /* PR_VALUE_SMBFINDNCLOSE */
+ "SMBtcon", /* PR_VALUE_SMBTCON */
+ "SMBtdis", /* PR_VALUE_SMBTDIS */
+ "SMBnegprot", /* PR_VALUE_SMBNEGPROT */
+ "SMBsesssetupX", /* PR_VALUE_SMBSESSSETUPX */
+ "SMBulogoffX", /* PR_VALUE_SMBULOGOFFX */
+ "SMBtconX", /* PR_VALUE_SMBTCONX */
+ "SMBdskattr", /* PR_VALUE_SMBDSKATTR */
+ "SMBsearch", /* PR_VALUE_SMBSEARCH */
+ "SMBffirst", /* PR_VALUE_SMBFFIRST */
+ "SMBfunique", /* PR_VALUE_SMBFUNIQUE */
+ "SMBfclose", /* PR_VALUE_SMBFCLOSE */
+ "SMBnttrans", /* PR_VALUE_SMBNTTRANS */
+ "SMBnttranss", /* PR_VALUE_SMBNTTRANSS */
+ "SMBntcreateX", /* PR_VALUE_SMBNTCREATEX */
+ "SMBntcancel", /* PR_VALUE_SMBNTCANCEL */
+ "SMBntrename", /* PR_VALUE_SMBNTRENAME */
+ "SMBsplopen", /* PR_VALUE_SMBSPLOPEN */
+ "SMBsplwr", /* PR_VALUE_SMBSPLWR */
+ "SMBsplclose", /* PR_VALUE_SMBSPLCLOSE */
+ "SMBsplretq", /* PR_VALUE_SMBSPLRETQ */
+ "SMBsends", /* PR_VALUE_SMBSENDS */
+ "SMBsendb", /* PR_VALUE_SMBSENDB */
+ "SMBfwdname", /* PR_VALUE_SMBFWDNAME */
+ "SMBcancelf", /* PR_VALUE_SMBCANCELF */
+ "SMBgetmac", /* PR_VALUE_SMBGETMAC */
+ "SMBsendstrt", /* PR_VALUE_SMBSENDSTRT */
+ "SMBsendend", /* PR_VALUE_SMBSENDEND */
+ "SMBsendtxt", /* PR_VALUE_SMBSENDTXT */
+ "SMBinvalid", /* PR_VALUE_SMBINVALID */
+ "pathworks_setdir", /* PR_VALUE_PATHWORKS_SETDIR */
+ "Trans2_open", /* PR_VALUE_TRANS2_OPEN */
+ "Trans2_findfirst", /* PR_VALUE_TRANS2_FINDFIRST */
+ "Trans2_findnext", /* PR_VALUE_TRANS2_FINDNEXT */
+ "Trans2_qfsinfo", /* PR_VALUE_TRANS2_QFSINFO */
+ "Trans2_setfsinfo", /* PR_VALUE_TRANS2_SETFSINFO */
+ "Trans2_qpathinfo", /* PR_VALUE_TRANS2_QPATHINFO */
+ "Trans2_setpathinfo", /* PR_VALUE_TRANS2_SETPATHINFO */
+ "Trans2_qfileinfo", /* PR_VALUE_TRANS2_QFILEINFO */
+ "Trans2_setfileinfo", /* PR_VALUE_TRANS2_SETFILEINFO */
+ "Trans2_fsctl", /* PR_VALUE_TRANS2_FSCTL */
+ "Trans2_ioctl", /* PR_VALUE_TRANS2_IOCTL */
+ "Trans2_findnotifyfirst", /* PR_VALUE_TRANS2_FINDNOTIFYFIRST */
+ "Trans2_findnotifynext", /* PR_VALUE_TRANS2_FINDNOTIFYNEXT */
+ "Trans2_mkdir", /* PR_VALUE_TRANS2_MKDIR */
+ "Trans2_session_setup", /* PR_VALUE_TRANS2_SESSION_SETUP */
+ "Trans2_get_dfs_referral", /* PR_VALUE_TRANS2_GET_DFS_REFERRAL */
+ "Trans2_report_dfs_inconsistancy", /* PR_VALUE_TRANS2_REPORT_DFS_INCONSISTANCY */
+ "NT_transact_create", /* PR_VALUE_NT_TRANSACT_CREATE */
+ "NT_transact_ioctl", /* PR_VALUE_NT_TRANSACT_IOCTL */
+ "NT_transact_set_security_desc", /* PR_VALUE_NT_TRANSACT_SET_SECURITY_DESC */
+ "NT_transact_notify_change",/* PR_VALUE_NT_TRANSACT_NOTIFY_CHANGE */
+ "NT_transact_rename", /* PR_VALUE_NT_TRANSACT_RENAME */
+ "NT_transact_query_security_desc", /* PR_VALUE_NT_TRANSACT_QUERY_SECURITY_DESC */
+ "NT_transact_get_user_quota",/* PR_VALUE_NT_TRANSACT_GET_USER_QUOTA */
+ "NT_transact_set_user_quota",/* PR_VALUE_NT_TRANSACT_SET_USER_QUOTA */
+ "get_nt_acl", /* PR_VALUE_GET_NT_ACL */
+ "fget_nt_acl", /* PR_VALUE_FGET_NT_ACL */
+ "set_nt_acl", /* PR_VALUE_SET_NT_ACL */
+ "fset_nt_acl", /* PR_VALUE_FSET_NT_ACL */
+ "chmod_acl", /* PR_VALUE_CHMOD_ACL */
+ "fchmod_acl", /* PR_VALUE_FCHMOD_ACL */
+ "name_release", /* PR_VALUE_NAME_RELEASE */
+ "name_refresh", /* PR_VALUE_NAME_REFRESH */
+ "name_registration", /* PR_VALUE_NAME_REGISTRATION */
+ "node_status", /* PR_VALUE_NODE_STATUS */
+ "name_query", /* PR_VALUE_NAME_QUERY */
+ "host_announce", /* PR_VALUE_HOST_ANNOUNCE */
+ "workgroup_announce", /* PR_VALUE_WORKGROUP_ANNOUNCE */
+ "local_master_announce", /* PR_VALUE_LOCAL_MASTER_ANNOUNCE */
+ "master_browser_announce", /* PR_VALUE_MASTER_BROWSER_ANNOUNCE */
+ "lm_host_announce", /* PR_VALUE_LM_HOST_ANNOUNCE */
+ "get_backup_list", /* PR_VALUE_GET_BACKUP_LIST */
+ "reset_browser", /* PR_VALUE_RESET_BROWSER */
+ "announce_request", /* PR_VALUE_ANNOUNCE_REQUEST */
+ "lm_announce_request", /* PR_VALUE_LM_ANNOUNCE_REQUEST */
+ "domain_logon", /* PR_VALUE_DOMAIN_LOGON */
+ "sync_browse_lists", /* PR_VALUE_SYNC_BROWSE_LISTS */
+ "run_elections", /* PR_VALUE_RUN_ELECTIONS */
+ "election", /* PR_VALUE_ELECTION */
+ "" /* PR_VALUE_MAX */
+ };
+
+ SMB_ASSERT(val >= 0);
+ SMB_ASSERT(val < PR_VALUE_MAX);
+ return valnames[val];
+}
+
#endif /* WITH_PROFILE */
diff --git a/source/python/py_lsa.c b/source/python/py_lsa.c
index 915223a5bb7..068190c0202 100644
--- a/source/python/py_lsa.c
+++ b/source/python/py_lsa.c
@@ -147,7 +147,7 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args)
const char **names;
DOM_SID *sids;
TALLOC_CTX *mem_ctx = NULL;
- uint32 *name_types;
+ enum lsa_SidType *name_types;
if (!PyArg_ParseTuple(args, "O", &py_names))
return NULL;
diff --git a/source/python/py_smb.c b/source/python/py_smb.c
index 679c113f397..2f5d1161d87 100644
--- a/source/python/py_smb.c
+++ b/source/python/py_smb.c
@@ -43,7 +43,7 @@ static PyObject *py_smb_connect(PyObject *self, PyObject *args, PyObject *kw)
if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &server))
return NULL;
- if (!(cli = cli_initialise(NULL)))
+ if (!(cli = cli_initialise()))
return NULL;
ZERO_STRUCT(ip);
@@ -99,7 +99,7 @@ static PyObject *py_smb_session_setup(PyObject *self, PyObject *args,
static char *kwlist[] = { "creds", NULL };
PyObject *creds;
char *username, *domain, *password, *errstr;
- BOOL result;
+ NTSTATUS result;
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O", kwlist, &creds))
return NULL;
@@ -118,7 +118,7 @@ static PyObject *py_smb_session_setup(PyObject *self, PyObject *args,
return NULL;
}
- return Py_BuildValue("i", result);
+ return Py_BuildValue("i", NT_STATUS_IS_OK(result));
}
static PyObject *py_smb_tconx(PyObject *self, PyObject *args, PyObject *kw)
diff --git a/source/registry/reg_cachehook.c b/source/registry/reg_cachehook.c
index 32885be8e2e..ae8420776ac 100644
--- a/source/registry/reg_cachehook.c
+++ b/source/registry/reg_cachehook.c
@@ -79,7 +79,7 @@ REGISTRY_HOOK* reghook_cache_find( const char *keyname )
/* prepend the string with a '\' character */
len = strlen( keyname );
- if ( !(key = SMB_MALLOC( len + 2 )) ) {
+ if ( !(key = (char *)SMB_MALLOC( len + 2 )) ) {
DEBUG(0,("reghook_cache_find: malloc failed for string [%s] !?!?!\n",
keyname));
return NULL;
@@ -94,7 +94,7 @@ REGISTRY_HOOK* reghook_cache_find( const char *keyname )
DEBUG(10,("reghook_cache_find: Searching for keyname [%s]\n", key));
- hook = pathtree_find( cache_tree, key ) ;
+ hook = (REGISTRY_HOOK *)pathtree_find( cache_tree, key ) ;
SAFE_FREE( key );
diff --git a/source/registry/reg_db.c b/source/registry/reg_db.c
index 5484c238b60..954cb6cf786 100644
--- a/source/registry/reg_db.c
+++ b/source/registry/reg_db.c
@@ -96,6 +96,20 @@ static BOOL init_registry_data( void )
int i;
const char *p, *p2;
UNISTR2 data;
+
+ /*
+ * There are potentially quite a few store operations which are all
+ * indiviually wrapped in tdb transactions. Wrapping them in a single
+ * transaction gives just a single transaction_commit() to actually do
+ * its fsync()s. See tdb/common/transaction.c for info about nested
+ * transaction behaviour.
+ */
+
+ if ( tdb_transaction_start( tdb_reg ) == -1 ) {
+ DEBUG(0, ("init_registry_data: tdb_transaction_start "
+ "failed\n"));
+ return False;
+ }
/* loop over all of the predefined paths and add each component */
@@ -135,14 +149,14 @@ static BOOL init_registry_data( void )
if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
DEBUG(0,("talloc() failure!\n"));
- return False;
+ goto fail;
}
regdb_fetch_keys( base, subkeys );
if ( *subkeyname )
regsubkey_ctr_addkey( subkeys, subkeyname );
if ( !regdb_store_keys( base, subkeys ))
- return False;
+ goto fail;
TALLOC_FREE( subkeys );
}
@@ -153,7 +167,7 @@ static BOOL init_registry_data( void )
for ( i=0; builtin_registry_values[i].path != NULL; i++ ) {
if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
DEBUG(0,("talloc() failure!\n"));
- return False;
+ goto fail;
}
regdb_fetch_values( builtin_registry_values[i].path, values );
@@ -190,7 +204,22 @@ static BOOL init_registry_data( void )
TALLOC_FREE( values );
}
+ if (tdb_transaction_commit( tdb_reg ) == -1) {
+ DEBUG(0, ("init_registry_data: Could not commit "
+ "transaction\n"));
+ return False;
+ }
+
return True;
+
+ fail:
+
+ if (tdb_transaction_cancel( tdb_reg ) == -1) {
+ smb_panic("init_registry_data: tdb_transaction_cancel "
+ "failed\n");
+ }
+
+ return False;
}
/***********************************************************************
@@ -229,7 +258,7 @@ BOOL regdb_init( void )
/* always setup the necessary keys and values */
if ( !init_registry_data() ) {
- DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
+ DEBUG(0,("init_registry: Failed to initialize data in registry!\n"));
return False;
}
@@ -313,7 +342,9 @@ static BOOL regdb_store_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
/* allocate some initial memory */
- buffer = SMB_MALLOC(sizeof(pstring));
+ if (!(buffer = (char *)SMB_MALLOC(sizeof(pstring)))) {
+ return False;
+ }
buflen = sizeof(pstring);
len = 0;
@@ -327,7 +358,7 @@ static BOOL regdb_store_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
len += tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
if ( len > buflen ) {
/* allocate some extra space */
- if ((buffer = SMB_REALLOC( buffer, len*2 )) == NULL) {
+ if ((buffer = (char *)SMB_REALLOC( buffer, len*2 )) == NULL) {
DEBUG(0,("regdb_store_keys: Failed to realloc memory of size [%d]\n", len*2));
ret = False;
goto done;
diff --git a/source/registry/reg_frontend.c b/source/registry/reg_frontend.c
index d5a9d45e8c4..ed49cc998c7 100644
--- a/source/registry/reg_frontend.c
+++ b/source/registry/reg_frontend.c
@@ -368,9 +368,11 @@ WERROR regkey_open_internal( REGISTRY_KEY **regkey, const char *path,
/* initialization */
keyinfo->type = REG_KEY_GENERIC;
- keyinfo->name = talloc_strdup( keyinfo, path );
-
-
+ if (!(keyinfo->name = talloc_strdup(keyinfo, path))) {
+ result = WERR_NOMEM;
+ goto done;
+ }
+
/* Tag this as a Performance Counter Key */
if( StrnCaseCmp(path, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
diff --git a/source/registry/reg_objects.c b/source/registry/reg_objects.c
index ecad94f1d6c..83fd85658fb 100644
--- a/source/registry/reg_objects.c
+++ b/source/registry/reg_objects.c
@@ -181,7 +181,8 @@ REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
if ( val->data_p && val->size )
{
- if ( !(copy->data_p = memdup( val->data_p, val->size )) ) {
+ if ( !(copy->data_p = (uint8 *)memdup( val->data_p,
+ val->size )) ) {
DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
val->size));
SAFE_FREE( copy );
@@ -307,7 +308,8 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type,
fstrcpy( ctr->values[ctr->num_values]->valuename, name );
ctr->values[ctr->num_values]->type = type;
- ctr->values[ctr->num_values]->data_p = TALLOC_MEMDUP( ctr, data_p, size );
+ ctr->values[ctr->num_values]->data_p = (uint8 *)TALLOC_MEMDUP(
+ ctr, data_p, size );
ctr->values[ctr->num_values]->size = size;
ctr->num_values++;
@@ -346,7 +348,8 @@ int regval_ctr_copyvalue( REGVAL_CTR *ctr, REGISTRY_VALUE *val )
fstrcpy( ctr->values[ctr->num_values]->valuename, val->valuename );
ctr->values[ctr->num_values]->type = val->type;
- ctr->values[ctr->num_values]->data_p = TALLOC_MEMDUP( ctr, val->data_p, val->size );
+ ctr->values[ctr->num_values]->data_p = (uint8 *)TALLOC_MEMDUP(
+ ctr, val->data_p, val->size );
ctr->values[ctr->num_values]->size = val->size;
ctr->num_values++;
}
diff --git a/source/registry/reg_perfcount.c b/source/registry/reg_perfcount.c
index 04a99c3af69..3625a417200 100644
--- a/source/registry/reg_perfcount.c
+++ b/source/registry/reg_perfcount.c
@@ -31,6 +31,8 @@
#define NAMES_DB "names.tdb"
#define DATA_DB "data.tdb"
+PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind);
+
/*********************************************************************
*********************************************************************/
@@ -177,7 +179,7 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
}
/* First encode the name_index */
working_size = (kbuf.dsize + 1)*sizeof(uint16);
- buf1 = SMB_REALLOC(buf1, buffer_size + working_size);
+ buf1 = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
if(!buf1) {
buffer_size = 0;
return buffer_size;
@@ -187,7 +189,7 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
buffer_size += working_size;
/* Now encode the actual name */
working_size = (dbuf.dsize + 1)*sizeof(uint16);
- buf1 = SMB_REALLOC(buf1, buffer_size + working_size);
+ buf1 = (char *)SMB_REALLOC(buf1, buffer_size + working_size);
if(!buf1) {
buffer_size = 0;
return buffer_size;
@@ -234,7 +236,7 @@ uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
/* Now terminate the MULTI_SZ with a double unicode NULL */
buf1 = *retbuf;
- buf1 = SMB_REALLOC(buf1, buffer_size + 2);
+ buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
if(!buf1) {
buffer_size = 0;
} else {
@@ -279,7 +281,7 @@ uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf)
/* Now terminate the MULTI_SZ with a double unicode NULL */
buf1 = *retbuf;
- buf1 = SMB_REALLOC(buf1, buffer_size + 2);
+ buf1 = (char *)SMB_REALLOC(buf1, buffer_size + 2);
if(!buf1) {
buffer_size = 0;
} else {
@@ -372,7 +374,7 @@ static BOOL _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
TDB_CONTEXT *names)
{
int i;
- BOOL success = False;
+ BOOL success = True;
PERF_OBJECT_TYPE *obj;
block->objects = (PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
@@ -397,12 +399,11 @@ static BOOL _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE;
block->NumObjectTypes+=1;
- for(i = 0; i < (int)obj->NumInstances; i++)
- {
+ for(i = 0; i < (int)obj->NumInstances; i++) {
success = _reg_perfcount_add_instance(obj, ps, i, names);
}
- return True;
+ return success;
}
/*********************************************************************
@@ -608,7 +609,7 @@ static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
char *begin, *end, *start, *stop;
int parent;
PERF_OBJECT_TYPE *obj;
- BOOL success = False;
+ BOOL success = True;
char buf[PERFCOUNT_MAX_LEN];
obj = NULL;
@@ -620,8 +621,7 @@ static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
return False;
start = begin+1;
- while(start < end)
- {
+ while(start < end) {
stop = index(start, ',');
if(stop == NULL)
stop = end;
@@ -629,8 +629,7 @@ static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
parent = atoi(start);
obj = _reg_perfcount_find_obj(block, parent);
- if(obj == NULL)
- {
+ if(obj == NULL) {
/* At this point we require that the parent object exist.
This can probably be handled better at some later time */
DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n",
@@ -657,7 +656,7 @@ static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
that the required instances are not there yet, so change NumInstances from
PERF_NO_INSTANCES to 0 */
- return True;
+ return success;
}
/*********************************************************************
@@ -755,13 +754,9 @@ BOOL _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj,
int instInd,
TDB_CONTEXT *names)
{
- BOOL success;
PERF_INSTANCE_DEFINITION *inst;
- success = False;
-
- if(obj->instances == NULL)
- {
+ if(obj->instances == NULL) {
obj->instances = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
obj->instances,
PERF_INSTANCE_DEFINITION,
@@ -772,9 +767,7 @@ BOOL _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj,
memset(&(obj->instances[instInd]), 0, sizeof(PERF_INSTANCE_DEFINITION));
inst = &(obj->instances[instInd]);
- success = _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names);
-
- return True;
+ return _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names);
}
/*********************************************************************
diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c
index 3ecff3d6964..10cfce604ef 100644
--- a/source/registry/reg_printing.c
+++ b/source/registry/reg_printing.c
@@ -382,7 +382,6 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *
UNISTR2 data;
char *p;
uint32 printer_status = PRINTER_STATUS_OK;
- int snum;
regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) );
regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) );
@@ -438,8 +437,7 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *
/* stream the device mode */
- snum = lp_servicenumber(info2->sharename);
- if ( (devmode = construct_dev_mode( snum )) != NULL ) {
+ if ( (devmode = construct_dev_mode( info2->sharename )) != NULL ) {
if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
offset = prs_offset( &prs );
regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
@@ -557,7 +555,7 @@ struct {
{ "UntilTime", REG_IDX_UNTILTIME },
{ "Name", REG_IDX_NAME },
{ "Location", REG_IDX_LOCATION },
- { "Descrioption", REG_IDX_DESCRIPTION },
+ { "Description", REG_IDX_DESCRIPTION },
{ "Parameters", REG_IDX_PARAMETERS },
{ "Port", REG_IDX_PORT },
{ "Share Name", REG_IDX_SHARENAME },
@@ -924,7 +922,7 @@ static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL
length = strlen(filename);
- buffer = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
+ buffer = (char *)SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
if ( !buffer ) {
break;
}
@@ -937,7 +935,7 @@ static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL
/* terminated by double NULL. Add the final one here */
- buffer = SMB_REALLOC( buffer, buffer_size + 2 );
+ buffer = (char *)SMB_REALLOC( buffer, buffer_size + 2 );
if ( !buffer ) {
buffer_size = 0;
} else {
diff --git a/source/registry/regfio.c b/source/registry/regfio.c
index f164d4e19d4..f2e95da8898 100644
--- a/source/registry/regfio.c
+++ b/source/registry/regfio.c
@@ -1646,7 +1646,9 @@ static BOOL create_vk_record( REGF_FILE *file, REGF_VK_REC *vk, REGISTRY_VALUE *
if ( vk->data_size > sizeof(uint32) ) {
uint32 data_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
- vk->data = TALLOC_MEMDUP( file->mem_ctx, regval_data_p(value), vk->data_size );
+ vk->data = (uint8 *)TALLOC_MEMDUP( file->mem_ctx,
+ regval_data_p(value),
+ vk->data_size );
if (vk->data == NULL) {
return False;
}
@@ -1746,7 +1748,6 @@ static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
if ( sec_desc ) {
uint32 sk_size = sk_record_data_size( sec_desc );
REGF_HBIN *sk_hbin;
- REGF_SK_REC *tmp = NULL;
/* search for it in the existing list of sd's */
@@ -1775,7 +1776,7 @@ static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
/* size value must be self-inclusive */
nk->sec_desc->size = sec_desc_size(sec_desc) + sizeof(uint32);
- DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, tmp );
+ DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, REGF_SK_REC *);
/* update the offsets for us and the previous sd in the list.
if this is the first record, then just set the next and prev
diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c
index deb97724a0e..97d8326ede4 100644
--- a/source/rpc_client/cli_lsarpc.c
+++ b/source/rpc_client/cli_lsarpc.c
@@ -547,7 +547,7 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
POLICY_HND *pol, uint16 info_class,
char **domain_name, char **dns_name,
char **forest_name,
- struct uuid **domain_guid,
+ struct GUID **domain_guid,
DOM_SID **domain_sid)
{
prs_struct qbuf, rbuf;
@@ -606,13 +606,13 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
}
if (domain_guid) {
- *domain_guid = TALLOC_P(mem_ctx, struct uuid);
+ *domain_guid = TALLOC_P(mem_ctx, struct GUID);
if (!*domain_guid) {
return NT_STATUS_NO_MEMORY;
}
memcpy(*domain_guid,
&r.ctr.info.id12.dom_guid,
- sizeof(struct uuid));
+ sizeof(struct GUID));
}
if (domain_sid && r.ctr.info.id12.ptr_dom_sid != 0) {
diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c
index 3a892cb7f4e..7296c45ebc4 100644
--- a/source/rpc_client/cli_netlogon.c
+++ b/source/rpc_client/cli_netlogon.c
@@ -424,12 +424,12 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
const char *server_name,
const char *domain_name,
- struct uuid *domain_guid,
- struct uuid *site_guid,
+ struct GUID *domain_guid,
+ struct GUID *site_guid,
uint32_t flags,
char **dc_unc, char **dc_address,
int32 *dc_address_type,
- struct uuid *domain_guid_out,
+ struct GUID *domain_guid_out,
char **domain_name_out,
char **forest_name,
uint32 *dc_flags,
@@ -638,7 +638,7 @@ NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
/* Sam synchronisation */
NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- uint32 database_id, UINT64_S seqnum,
+ uint32 database_id, uint64 seqnum,
uint32 *num_deltas,
SAM_DELTA_HDR **hdr_deltas,
SAM_DELTA_CTR **deltas)
@@ -695,6 +695,7 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
const char *domain,
const char *username,
const char *password,
+ const char *workstation,
int logon_type)
{
prs_struct qbuf, rbuf;
@@ -712,7 +713,11 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
ZERO_STRUCT(r);
ZERO_STRUCT(ret_creds);
- fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
+ if (workstation) {
+ fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
+ } else {
+ fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
+ }
/* Initialise input parameters */
diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c
index 467e652ca99..61f5ee51bd0 100644
--- a/source/rpc_client/cli_pipe.c
+++ b/source/rpc_client/cli_pipe.c
@@ -927,7 +927,7 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
/* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
- &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL);
+ &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
if (ret) {
DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
@@ -2261,7 +2261,13 @@ struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe
*perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(0, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
+ int lvl = 0;
+ if (pipe_idx == PI_LSARPC_DS) {
+ /* non AD domains just don't have this pipe, avoid
+ * level 0 statement in that case - gd */
+ lvl = 3;
+ }
+ DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
cli_rpc_pipe_close(result);
return NULL;
diff --git a/source/rpc_client/cli_reg.c b/source/rpc_client/cli_reg.c
index 87ab5dc9dad..e136df753ad 100644
--- a/source/rpc_client/cli_reg.c
+++ b/source/rpc_client/cli_reg.c
@@ -521,7 +521,7 @@ WERROR rpccli_reg_enum_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
else
fstrcpy( class_name, "" );
- *mod_time = nt_time_to_unix(out.time);
+ *mod_time = nt_time_to_unix(*out.time);
return out.status;
}
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index ea8db636423..26b2b002d7c 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -1288,6 +1288,55 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
return result;
}
+/* User change password given blobs */
+
+NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *username,
+ DATA_BLOB new_nt_password,
+ DATA_BLOB old_nt_hash_enc,
+ DATA_BLOB new_lm_password,
+ DATA_BLOB old_lm_hash_enc)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_CHGPASSWD_USER q;
+ SAMR_R_CHGPASSWD_USER r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
+
+ DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_samr_q_chgpasswd_user(&q, srv_name_slash, username,
+ new_nt_password.data,
+ old_nt_hash_enc.data,
+ new_lm_password.data,
+ old_lm_hash_enc.data);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_chgpasswd_user,
+ samr_io_r_chgpasswd_user,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ if (!NT_STATUS_IS_OK(result = r.status)) {
+ goto done;
+ }
+
+ done:
+
+ return result;
+}
+
+
/* change password 3 */
NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c
index d6d4417da37..75c617c944c 100644
--- a/source/rpc_client/cli_spoolss.c
+++ b/source/rpc_client/cli_spoolss.c
@@ -1609,7 +1609,7 @@ WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *me
/* Return output parameters */
- value->data_p = TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
+ value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
value->type = out.type;
value->size = out.size;
@@ -1662,7 +1662,7 @@ WERROR rpccli_spoolss_getprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *
/* Return output parameters */
- value->data_p = TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
+ value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
value->type = out.type;
value->size = out.needed;
@@ -1758,7 +1758,8 @@ WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *m
if (value) {
rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
STR_TERMINATE);
- value->data_p = TALLOC_MEMDUP(mem_ctx, out.data, out.realdatasize);
+ value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
+ out.realdatasize);
value->type = out.type;
value->size = out.realdatasize;
}
diff --git a/source/rpc_client/cli_wkssvc.c b/source/rpc_client/cli_wkssvc.c
deleted file mode 100644
index d8e97beb649..00000000000
--- a/source/rpc_client/cli_wkssvc.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NT Domain Authentication SMB / MSRPC client
- Copyright (C) Andrew Tridgell 1994-2000
- Copyright (C) Tim Potter 2001
- Copyright (C) Rafal Szczesniak 2002
- Copyright (C) Jeremy Allison 2005.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (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"
-
-/**
- * WksQueryInfo rpc call (like query for server's capabilities)
- *
- * @param initialised client structure with \PIPE\wkssvc opened
- * @param mem_ctx memory context assigned to this rpc binding
- * @param wks100 WksQueryInfo structure
- *
- * @return NTSTATUS of rpc call
- */
-
-NTSTATUS rpccli_wks_query_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- WKS_INFO_100 *wks100)
-{
- prs_struct qbuf;
- prs_struct rbuf;
- WKS_Q_QUERY_INFO q;
- WKS_R_QUERY_INFO r;
-
- if (cli == NULL || wks100 == NULL)
- return NT_STATUS_UNSUCCESSFUL;
-
- DEBUG(4, ("WksQueryInfo\n"));
-
- /* init query structure with rpc call arguments */
- init_wks_q_query_info(&q, cli->cli->desthost, 100);
- r.wks100 = wks100;
-
- CLI_DO_RPC(cli, mem_ctx, PI_WKSSVC, WKS_QUERY_INFO,
- q, r,
- qbuf, rbuf,
- wks_io_q_query_info,
- wks_io_r_query_info,
- NT_STATUS_UNSUCCESSFUL);
-
- /* check returnet status code */
- if (NT_STATUS_IS_ERR(r.status)) {
- /* report the error */
- DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r.status)));
- return r.status;
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source/rpc_client/ndr.c b/source/rpc_client/ndr.c
new file mode 100644
index 00000000000..82b9079a28d
--- /dev/null
+++ b/source/rpc_client/ndr.c
@@ -0,0 +1,92 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr interface
+
+ Copyright (C) Jelmer Vernooij 2006
+
+ 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"
+
+
+NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int p_idx, int opnum, void *data,
+ ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn)
+{
+ prs_struct q_ps, r_ps;
+ struct ndr_pull *pull;
+ DATA_BLOB blob;
+ struct ndr_push *push;
+ NTSTATUS status;
+
+ SMB_ASSERT(cli->pipe_idx == p_idx);
+
+ push = ndr_push_init_ctx(mem_ctx);
+ if (!push) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = push_fn(push, NDR_IN, data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ blob = ndr_push_blob(push);
+
+ if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ talloc_free(push);
+
+ if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) {
+ prs_mem_free( &q_ps );
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps);
+
+ prs_mem_free( &q_ps );
+
+ if (!NT_STATUS_IS_OK(status)) {
+ prs_mem_free( &r_ps );
+ return status;
+ }
+
+ if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
+ prs_mem_free( &r_ps );
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ prs_mem_free( &r_ps );
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx);
+ if (pull == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* have the ndr parser alloc memory for us */
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ status = pull_fn(pull, NDR_OUT, data);
+ talloc_free(pull);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source/rpc_parse/parse_buffer.c b/source/rpc_parse/parse_buffer.c
index 21dddfa3cf5..5643189afea 100644
--- a/source/rpc_parse/parse_buffer.c
+++ b/source/rpc_parse/parse_buffer.c
@@ -319,7 +319,8 @@ BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16
/* Yes this should be malloc not talloc. Don't change. */
- chaine.buffer = SMB_MALLOC((q-p+1)*sizeof(uint16));
+ chaine.buffer = (uint16 *)
+ SMB_MALLOC((q-p+1)*sizeof(uint16));
if (chaine.buffer == NULL)
return False;
diff --git a/source/rpc_parse/parse_dfs.c b/source/rpc_parse/parse_dfs.c
index fde3dc6e03a..e590aae0526 100644
--- a/source/rpc_parse/parse_dfs.c
+++ b/source/rpc_parse/parse_dfs.c
@@ -340,7 +340,7 @@ BOOL netdfs_io_dfs_Info3_d(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps
return True;
}
-BOOL init_netdfs_dfs_Info4(NETDFS_DFS_INFO4 *v, const char *path, const char *comment, uint32 state, uint32 timeout, struct uuid guid, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
+BOOL init_netdfs_dfs_Info4(NETDFS_DFS_INFO4 *v, const char *path, const char *comment, uint32 state, uint32 timeout, struct GUID guid, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
{
DEBUG(5,("init_netdfs_dfs_Info4\n"));
diff --git a/source/rpc_parse/parse_eventlog.c b/source/rpc_parse/parse_eventlog.c
index 4aff9734eed..addf433feb8 100644
--- a/source/rpc_parse/parse_eventlog.c
+++ b/source/rpc_parse/parse_eventlog.c
@@ -54,7 +54,7 @@ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u
if(!prs_align(ps))
return False;
- if ( !prs_pointer("", ps, depth, (void**)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0))
+ if ( !prs_pointer("", ps, depth, (void*)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0))
return False;
if ( !prs_unistr4("logname", ps, depth, &q_u->logname) )
diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c
index 0b138aba1b4..e1630f79f48 100644
--- a/source/rpc_parse/parse_lsa.c
+++ b/source/rpc_parse/parse_lsa.c
@@ -664,7 +664,7 @@ BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *out,
if(!prs_uint32("count", ps, depth, &out->count))
return False;
- if ( !prs_pointer("trusted_domains", ps, depth, (void**)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list))
+ if ( !prs_pointer("trusted_domains", ps, depth, (void*)&out->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list))
return False;
if(!prs_ntstatus("status", ps, depth, &out->status))
@@ -2922,7 +2922,7 @@ BOOL lsa_io_r_setsystemaccount(const char *desc, LSA_R_SETSYSTEMACCOUNT *out, p
}
-static void init_lsa_string( LSA_STRING *uni, const char *string )
+void init_lsa_string( LSA_STRING *uni, const char *string )
{
init_unistr2(&uni->unistring, string, UNI_FLAGS_NONE);
init_uni_hdr(&uni->hdr, &uni->unistring);
@@ -3253,7 +3253,7 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *out, pr
if(!prs_uint32("count ", ps, depth, &out->count))
return False;
- if ( !prs_pointer("rights", ps, depth, (void**)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+ if ( !prs_pointer("rights", ps, depth, (void*)&out->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
return False;
if(!prs_align(ps))
@@ -3305,7 +3305,7 @@ BOOL lsa_io_q_add_acct_rights(const char *desc, LSA_Q_ADD_ACCT_RIGHTS *in, prs_s
if(!prs_uint32("count", ps, depth, &in->count))
return False;
- if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+ if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
return False;
return True;
@@ -3374,7 +3374,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *in,
if(!prs_uint32("count", ps, depth, &in->count))
return False;
- if ( !prs_pointer("rights", ps, depth, (void**)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
+ if ( !prs_pointer("rights", ps, depth, (void*)&in->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
return False;
return True;
@@ -4059,7 +4059,7 @@ BOOL lsa_io_r_query_trusted_domain_info(const char *desc,
prs_debug(ps, depth, desc, "lsa_io_r_query_trusted_domain_info");
depth++;
- if (!prs_pointer("trustdom", ps, depth, (void**)&r_q->info,
+ if (!prs_pointer("trustdom", ps, depth, (void*)&r_q->info,
sizeof(LSA_TRUSTED_DOMAIN_INFO),
(PRS_POINTER_CAST)lsa_io_trustdom_query) )
return False;
@@ -4188,7 +4188,7 @@ BOOL lsa_io_r_query_dom_info(const char *desc, LSA_R_QUERY_DOM_INFO_POLICY *out,
prs_debug(ps, depth, desc, "lsa_io_r_query_dom_info");
depth++;
- if (!prs_pointer("dominfo", ps, depth, (void**)&out->info,
+ if (!prs_pointer("dominfo", ps, depth, (void*)&out->info,
sizeof(LSA_DOM_INFO_UNION),
(PRS_POINTER_CAST)lsa_io_dom_info_query) )
return False;
diff --git a/source/rpc_parse/parse_misc.c b/source/rpc_parse/parse_misc.c
index cb7c06eb459..3b1e9a4f08e 100644
--- a/source/rpc_parse/parse_misc.c
+++ b/source/rpc_parse/parse_misc.c
@@ -115,6 +115,7 @@ static BOOL smb_io_utime(const char *desc, UTIME *t, prs_struct *ps, int depth)
BOOL smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
{
+ uint32 low, high;
if (nttime == NULL)
return False;
@@ -124,11 +125,20 @@ BOOL smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
if(!prs_align(ps))
return False;
- if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
+ if (MARSHALLING(ps)) {
+ low = *nttime & 0xFFFFFFFF;
+ high = *nttime >> 32;
+ }
+
+ if(!prs_uint32("low ", ps, depth, &low)) /* low part */
return False;
- if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
+ if(!prs_uint32("high", ps, depth, &high)) /* high part */
return False;
+ if (UNMARSHALLING(ps)) {
+ *nttime = (((uint64_t)high << 32) + low);
+ }
+
return True;
}
@@ -288,10 +298,10 @@ BOOL smb_io_dom_sid2(const char *desc, DOM_SID2 *sid, prs_struct *ps, int depth)
}
/*******************************************************************
- Reads or writes a struct uuid
+ Reads or writes a struct GUID
********************************************************************/
-BOOL smb_io_uuid(const char *desc, struct uuid *uuid,
+BOOL smb_io_uuid(const char *desc, struct GUID *uuid,
prs_struct *ps, int depth)
{
if (uuid == NULL)
@@ -518,7 +528,7 @@ BOOL smb_io_unistr(const char *desc, UNISTR *uni, prs_struct *ps, int depth)
size_t create_rpc_blob(RPC_DATA_BLOB *str, size_t len)
{
- str->buffer = TALLOC_ZERO(get_talloc_ctx(), len);
+ str->buffer = (uint8 *)TALLOC_ZERO(get_talloc_ctx(), len);
if (str->buffer == NULL)
smb_panic("create_rpc_blob: talloc fail\n");
return len;
@@ -617,7 +627,8 @@ void init_regval_buffer(REGVAL_BUFFER *str, const uint8 *buf, size_t len)
if (buf != NULL) {
SMB_ASSERT(str->buf_max_len >= str->buf_len);
- str->buffer = TALLOC_ZERO(get_talloc_ctx(), str->buf_max_len);
+ str->buffer = (uint16 *)TALLOC_ZERO(get_talloc_ctx(),
+ str->buf_max_len);
if (str->buffer == NULL)
smb_panic("init_regval_buffer: talloc fail\n");
memcpy(str->buffer, buf, str->buf_len);
@@ -723,7 +734,8 @@ void init_string2(STRING2 *str, const char *buf, size_t max_len, size_t str_len)
/* store the string */
if(str_len != 0) {
- str->buffer = TALLOC_ZERO(get_talloc_ctx(), str->str_max_len);
+ str->buffer = (uint8 *)TALLOC_ZERO(get_talloc_ctx(),
+ str->str_max_len);
if (str->buffer == NULL)
smb_panic("init_string2: malloc fail\n");
memcpy(str->buffer, buf, str_len);
@@ -1690,15 +1702,9 @@ BOOL smb_io_pol_hnd(const char *desc, POLICY_HND *pol, prs_struct *ps, int depth
if(UNMARSHALLING(ps))
ZERO_STRUCTP(pol);
- if (!prs_uint32("data1", ps, depth, &pol->data1))
+ if (!prs_uint32("handle_type", ps, depth, &pol->handle_type))
return False;
- if (!prs_uint32("data2", ps, depth, &pol->data2))
- return False;
- if (!prs_uint16("data3", ps, depth, &pol->data3))
- return False;
- if (!prs_uint16("data4", ps, depth, &pol->data4))
- return False;
- if(!prs_uint8s (False, "data5", ps, depth, pol->data5, sizeof(pol->data5)))
+ if (!smb_io_uuid("uuid", (struct GUID*)&pol->uuid, ps, depth))
return False;
return True;
@@ -1760,10 +1766,25 @@ BOOL smb_io_unistr3(const char *desc, UNISTR3 *name, prs_struct *ps, int depth)
/*******************************************************************
Stream a uint64_struct
********************************************************************/
-BOOL prs_uint64(const char *name, prs_struct *ps, int depth, UINT64_S *data64)
+BOOL prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64)
{
- return prs_uint32(name, ps, depth+1, &data64->low) &&
- prs_uint32(name, ps, depth+1, &data64->high);
+ if (UNMARSHALLING(ps)) {
+ uint32 high, low;
+
+ if (!prs_uint32(name, ps, depth+1, &low))
+ return False;
+
+ if (!prs_uint32(name, ps, depth+1, &high))
+ return False;
+
+ *data64 = ((uint64_t)high << 32) + low;
+
+ return True;
+ } else {
+ uint32 high = (*data64) >> 32, low = (*data64) & 0xFFFFFFFF;
+ return prs_uint32(name, ps, depth+1, &low) &&
+ prs_uint32(name, ps, depth+1, &high);
+ }
}
/*******************************************************************
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index bc6b32e6ead..2ccc9f59f68 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -485,7 +485,7 @@ BOOL net_io_r_logon_ctrl(const char *desc, NET_R_LOGON_CTRL *r_l, prs_struct *ps
void init_net_q_getdcname(NET_Q_GETDCNAME *r_t, const char *logon_server,
const char *domainname)
{
- DEBUG(5,("init_r_getdcname\n"));
+ DEBUG(5,("init_q_getdcname\n"));
r_t->ptr_logon_server = (logon_server != NULL);
init_unistr2(&r_t->uni_logon_server, logon_server, UNI_STR_TERMINATE);
@@ -1522,7 +1522,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
/* "other" sids are set up above */
}
- void dump_acct_flags(uint32 acct_flags) {
+static void dump_acct_flags(uint32 acct_flags) {
int lvl = 10;
DEBUG(lvl,("dump_acct_flags\n"));
@@ -1549,7 +1549,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
}
}
- void dump_user_flgs(uint32 user_flags) {
+static void dump_user_flgs(uint32 user_flags) {
int lvl = 10;
DEBUG(lvl,("dump_user_flgs\n"));
@@ -3104,7 +3104,7 @@ makes a NET_Q_SAM_DELTAS structure.
********************************************************************/
BOOL init_net_q_sam_deltas(NET_Q_SAM_DELTAS *q_s, const char *srv_name,
const char *cli_name, DOM_CRED *cli_creds,
- uint32 database_id, UINT64_S dom_mod_count)
+ uint32 database_id, uint64 dom_mod_count)
{
DEBUG(5, ("init_net_q_sam_deltas\n"));
@@ -3115,8 +3115,7 @@ BOOL init_net_q_sam_deltas(NET_Q_SAM_DELTAS *q_s, const char *srv_name,
memset(&q_s->ret_creds, 0, sizeof(q_s->ret_creds));
q_s->database_id = database_id;
- q_s->dom_mod_count.low = dom_mod_count.low;
- q_s->dom_mod_count.high = dom_mod_count.high;
+ q_s->dom_mod_count = dom_mod_count;
q_s->max_size = 0xffff;
return True;
@@ -3233,8 +3232,8 @@ BOOL net_io_r_sam_deltas(const char *desc,
void init_net_q_dsr_getdcname(NET_Q_DSR_GETDCNAME *r_t, const char *server_unc,
const char *domain_name,
- struct uuid *domain_guid,
- struct uuid *site_guid,
+ struct GUID *domain_guid,
+ struct GUID *site_guid,
uint32_t flags)
{
DEBUG(5, ("init_net_q_dsr_getdcname\n"));
@@ -3291,7 +3290,7 @@ BOOL net_io_q_dsr_getdcname(const char *desc, NET_Q_DSR_GETDCNAME *r_t,
return False;
if (UNMARSHALLING(ps) && (r_t->ptr_domain_guid)) {
- r_t->domain_guid = PRS_ALLOC_MEM(ps, struct uuid, 1);
+ r_t->domain_guid = PRS_ALLOC_MEM(ps, struct GUID, 1);
if (r_t->domain_guid == NULL)
return False;
}
@@ -3307,7 +3306,7 @@ BOOL net_io_q_dsr_getdcname(const char *desc, NET_Q_DSR_GETDCNAME *r_t,
return False;
if (UNMARSHALLING(ps) && (r_t->ptr_site_guid)) {
- r_t->site_guid = PRS_ALLOC_MEM(ps, struct uuid, 1);
+ r_t->site_guid = PRS_ALLOC_MEM(ps, struct GUID, 1);
if (r_t->site_guid == NULL)
return False;
}
@@ -3330,7 +3329,7 @@ BOOL net_io_q_dsr_getdcname(const char *desc, NET_Q_DSR_GETDCNAME *r_t,
********************************************************************/
void init_net_r_dsr_getdcname(NET_R_DSR_GETDCNAME *r_t, const char *dc_unc,
const char *dc_address, int32 dc_address_type,
- struct uuid domain_guid, const char *domain_name,
+ struct GUID domain_guid, const char *domain_name,
const char *forest_name, uint32 dc_flags,
const char *dc_site_name,
const char *client_site_name)
diff --git a/source/rpc_parse/parse_ntsvcs.c b/source/rpc_parse/parse_ntsvcs.c
index 599257e8020..ab5f3f75e87 100644
--- a/source/rpc_parse/parse_ntsvcs.c
+++ b/source/rpc_parse/parse_ntsvcs.c
@@ -77,7 +77,7 @@ BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST
if(!prs_align(ps))
return False;
- if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+ if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
return False;
if ( !prs_align(ps) )
return False;
@@ -127,7 +127,7 @@ BOOL ntsvcs_io_q_get_device_list(const char *desc, NTSVCS_Q_GET_DEVICE_LIST *q_u
if(!prs_align(ps))
return False;
- if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+ if ( !prs_pointer("devicename", ps, depth, (void*)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
return False;
if( !prs_align(ps) )
return False;
diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c
index 14e190892d7..54bbe3adf6c 100644
--- a/source/rpc_parse/parse_prs.c
+++ b/source/rpc_parse/parse_prs.c
@@ -158,7 +158,8 @@ char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count)
if (size) {
/* We can't call the type-safe version here. */
- ret = _talloc_zero_array(ps->mem_ctx, size, count, "parse_prs");
+ ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count,
+ "parse_prs");
}
return ret;
}
@@ -213,7 +214,7 @@ BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize)
if (newsize == 0) {
SAFE_FREE(ps->data_p);
} else {
- ps->data_p = SMB_REALLOC(ps->data_p, newsize);
+ ps->data_p = (char *)SMB_REALLOC(ps->data_p, newsize);
if (ps->data_p == NULL) {
DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
@@ -265,7 +266,7 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space);
- if((ps->data_p = SMB_MALLOC(new_size)) == NULL) {
+ if((ps->data_p = (char *)SMB_MALLOC(new_size)) == NULL) {
DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
return False;
}
@@ -277,7 +278,7 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
*/
new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);
- if ((ps->data_p = SMB_REALLOC(ps->data_p, new_size)) == NULL) {
+ if ((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) {
DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
(unsigned int)new_size));
return False;
@@ -306,7 +307,7 @@ BOOL prs_force_grow(prs_struct *ps, uint32 extra_space)
return False;
}
- if((ps->data_p = SMB_REALLOC(ps->data_p, new_size)) == NULL) {
+ if((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) {
DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",
(unsigned int)new_size));
return False;
@@ -624,9 +625,10 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
********************************************************************/
BOOL prs_pointer( const char *name, prs_struct *ps, int depth,
- void **data, size_t data_size,
+ void *dta, size_t data_size,
BOOL(*prs_fn)(const char*, prs_struct*, int, void*) )
{
+ void ** data = (void **)dta;
uint32 data_p;
/* output f000baaa to stream if the pointer is non-zero. */
@@ -1459,7 +1461,7 @@ int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
kbuf.dsize = strlen(keystr)+1;
dbuf.dptr = ps->data_p;
dbuf.dsize = prs_offset(ps);
- return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ return tdb_trans_store(tdb, kbuf, dbuf, TDB_REPLACE);
}
/* useful function to fetch a structure into rpc wire format */
@@ -1624,7 +1626,7 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
uchar digest_final[16];
uchar confounder[8];
uchar seq_num[8];
- static const uchar nullbytes[8];
+ static const uchar nullbytes[8] = { 0, };
static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
@@ -1793,3 +1795,35 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l
return (memcmp(digest_final, verf->packet_digest,
sizeof(verf->packet_digest)) == 0);
}
+
+/*******************************************************************
+creates a new prs_struct containing a DATA_BLOB
+********************************************************************/
+BOOL prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+ if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL ))
+ return False;
+
+
+ if (!prs_copy_data_in(prs, (char *)blob->data, blob->length))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+return the contents of a prs_struct in a DATA_BLOB
+********************************************************************/
+BOOL prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+ blob->length = prs_data_size(prs);
+ blob->data = (uint8 *)talloc_zero_size(mem_ctx, blob->length);
+
+ /* set the pointer at the end of the buffer */
+ prs_set_offset( prs, prs_data_size(prs) );
+
+ if (!prs_copy_all_data_out((char *)blob->data, prs))
+ return False;
+
+ return True;
+}
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 0bde3da26c8..27a5ef9d996 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -6,7 +6,7 @@
* Copyright (C) Paul Ashton 1997-2000,
* Copyright (C) Elrond 2000,
* Copyright (C) Jeremy Allison 2001,
- * Copyright (C) Jean François Micouleau 1998-2001,
+ * Copyright (C) Jean François Micouleau 1998-2001,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002.
*
* This program is free software; you can redistribute it and/or modify
@@ -511,12 +511,10 @@ void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist,
u_1->password_properties = password_properties;
/* password never expire */
- u_1->expire.high = nt_expire.high;
- u_1->expire.low = nt_expire.low;
+ u_1->expire = nt_expire;
/* can change the password now */
- u_1->min_passwordage.high = nt_min_age.high;
- u_1->min_passwordage.low = nt_min_age.low;
+ u_1->min_passwordage = nt_min_age;
}
@@ -555,13 +553,11 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2,
const char *comment, const char *domain, const char *server,
uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout, uint32 server_role)
{
- u_2->logout.low = nt_logout.low;
- u_2->logout.high = nt_logout.high;
-
- u_2->seq_num.low = seq_num;
- u_2->seq_num.high = 0x00000000;
+ u_2->logout = nt_logout;
+ u_2->seq_num = seq_num;
+
u_2->unknown_4 = 0x00000001;
u_2->server_role = server_role;
u_2->unknown_6 = 0x00000001;
@@ -635,8 +631,7 @@ inits a structure.
void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout)
{
- u_3->logout.low = nt_logout.low;
- u_3->logout.high = nt_logout.high;
+ u_3->logout = nt_logout;
}
/*******************************************************************
@@ -789,8 +784,7 @@ inits a structure.
void init_unk_info8(SAM_UNK_INFO_8 * u_8, uint32 seq_num)
{
unix_to_nt_time(&u_8->domain_create_time, 0);
- u_8->seq_num.low = seq_num;
- u_8->seq_num.high = 0x0000;
+ u_8->seq_num = seq_num;
}
/*******************************************************************
@@ -849,10 +843,8 @@ inits a structure.
void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout)
{
- u_12->duration.low = nt_lock_duration.low;
- u_12->duration.high = nt_lock_duration.high;
- u_12->reset_count.low = nt_reset_time.low;
- u_12->reset_count.high = nt_reset_time.high;
+ u_12->duration = nt_lock_duration;
+ u_12->reset_count = nt_reset_time;
u_12->bad_attempt_lockout = lockout;
}
@@ -887,8 +879,7 @@ inits a structure.
void init_unk_info13(SAM_UNK_INFO_13 * u_13, uint32 seq_num)
{
unix_to_nt_time(&u_13->domain_create_time, 0);
- u_13->seq_num.low = seq_num;
- u_13->seq_num.high = 0x0000;
+ u_13->seq_num = seq_num;
u_13->unknown1 = 0;
u_13->unknown2 = 0;
}
@@ -3854,7 +3845,7 @@ BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO *out,
if(!prs_align(ps))
return False;
- if ( !prs_pointer("alias", ps, depth, (void**)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr))
+ if ( !prs_pointer("alias", ps, depth, (void*)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr))
return False;
if(!prs_align(ps))
return False;
@@ -4896,7 +4887,7 @@ inits a SAMR_R_LOOKUP_NAMES structure.
NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u,
uint32 num_rids,
- uint32 *rid, uint32 *type,
+ uint32 *rid, enum lsa_SidType *type,
NTSTATUS status)
{
DEBUG(5, ("init_samr_r_lookup_names\n"));
@@ -5587,7 +5578,8 @@ static BOOL sam_io_user_info17(const char *desc, SAM_USER_INFO_17 * usr,
init_sam_user_infoa
*************************************************************************/
-void init_sam_user_info24(SAM_USER_INFO_24 * usr, char newpass[516], uint16 pw_len)
+void init_sam_user_info24(SAM_USER_INFO_24 * usr, char newpass[516],
+ uint8 pw_len)
{
DEBUG(10, ("init_sam_user_info24:\n"));
memcpy(usr->pass, newpass, sizeof(usr->pass));
@@ -5615,10 +5607,10 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr,
return False;
if (MARSHALLING(ps) && (usr->pw_len != 0)) {
- if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
+ if (!prs_uint8("pw_len", ps, depth, &usr->pw_len))
return False;
} else if (UNMARSHALLING(ps)) {
- if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
+ if (!prs_uint8("pw_len", ps, depth, &usr->pw_len))
return False;
}
@@ -5741,8 +5733,8 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
copy_unistr2(&usr->uni_workstations, wkstas);
init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
- copy_unistr2(&usr->uni_unknown_str, unk_str);
- init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+ copy_unistr2(&usr->uni_comment, unk_str);
+ init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -5835,8 +5827,8 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
init_unistr2(&usr->uni_workstations, wkstas, UNI_FLAGS_NONE);
init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
- init_unistr2(&usr->uni_unknown_str, unk_str, UNI_FLAGS_NONE);
- init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+ init_unistr2(&usr->uni_comment, unk_str, UNI_FLAGS_NONE);
+ init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -5895,7 +5887,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
return False;
if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */
return False;
- if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */
+ if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */
return False;
if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */
return False;
@@ -5963,7 +5955,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */
return False;
- if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */
+ if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth)) /* unknown string */
return False;
if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -6025,7 +6017,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
return False;
if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */
return False;
- if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */
+ if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */
return False;
if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */
return False;
@@ -6076,7 +6068,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */
return False;
- if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */
+ if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth)) /* unknown string */
return False;
if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -6182,8 +6174,8 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
copy_unistr2(&usr->uni_workstations, wkstas);
init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
- copy_unistr2(&usr->uni_unknown_str, unk_str);
- init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+ copy_unistr2(&usr->uni_comment, unk_str);
+ init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -6208,6 +6200,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
pass_last_set_time, pass_can_change_time,
pass_must_change_time;
+ time_t must_change_time;
const char* user_name = pdb_get_username(pw);
const char* full_name = pdb_get_fullname(pw);
const char* home_dir = pdb_get_homedir(pw);
@@ -6232,12 +6225,16 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
}
/* Create NTTIME structs */
- unix_to_nt_time (&logon_time, pdb_get_logon_time(pw));
- unix_to_nt_time (&logoff_time, pdb_get_logoff_time(pw));
+ unix_to_nt_time (&logon_time, pdb_get_logon_time(pw));
+ unix_to_nt_time (&logoff_time, pdb_get_logoff_time(pw));
unix_to_nt_time (&kickoff_time, pdb_get_kickoff_time(pw));
- unix_to_nt_time (&pass_last_set_time, pdb_get_pass_last_set_time(pw));
- unix_to_nt_time (&pass_can_change_time, pdb_get_pass_can_change_time(pw));
- unix_to_nt_time (&pass_must_change_time,pdb_get_pass_must_change_time(pw));
+ unix_to_nt_time (&pass_last_set_time, pdb_get_pass_last_set_time(pw));
+ unix_to_nt_time (&pass_can_change_time,pdb_get_pass_can_change_time(pw));
+ must_change_time = pdb_get_pass_must_change_time(pw);
+ if (must_change_time == get_time_t_max())
+ unix_to_nt_time_abs(&pass_must_change_time, must_change_time);
+ else
+ unix_to_nt_time(&pass_must_change_time, must_change_time);
/* structure assignment */
usr->logon_time = logon_time;
@@ -6264,8 +6261,10 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
return NT_STATUS_UNSUCCESSFUL;
}
+ become_root();
group_sid = pdb_get_group_sid(pw);
-
+ unbecome_root();
+
if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
fstring group_sid_string;
fstring domain_sid_string;
@@ -6331,8 +6330,8 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *
init_unistr2(&usr->uni_workstations, workstations, UNI_STR_TERMINATE);
init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
- init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE);
- init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
+ init_unistr2(&usr->uni_comment, NULL, UNI_STR_TERMINATE);
+ init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
@@ -6398,7 +6397,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
return False;
if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth)) /* wkstas user can log on from */
return False;
- if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth)) /* unknown string */
+ if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth)) /* unknown string */
return False;
if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth)) /* wkstas user can log on from */
return False;
@@ -6438,25 +6437,25 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
/* here begins pointed-to data */
- if(!smb_io_unistr2("uni_user_name ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */
+ if(!smb_io_unistr2("uni_user_name ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_full_name ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */
+ if(!smb_io_unistr2("uni_full_name ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_home_dir ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth)) /* home directory unicode string */
+ if(!smb_io_unistr2("uni_home_dir ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_dir_drive ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth)) /* home directory drive unicode string */
+ if(!smb_io_unistr2("uni_dir_drive ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth)) /* logon script unicode string */
+ if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth)) /* profile path unicode string */
+ if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_acct_desc ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth)) /* user desc unicode string */
+ if(!smb_io_unistr2("uni_acct_desc ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth)) /* worksations user can log on from */
+ if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth)) /* unknown string */
+ if(!smb_io_unistr2("uni_comment", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))
return False;
- if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth)) /* worksations user can log on from */
+ if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth))
return False;
/* ok, this is only guess-work (as usual) */
@@ -7713,6 +7712,14 @@ BOOL samr_io_r_chgpasswd_user3(const char *desc, SAMR_R_CHGPASSWD_USER3 *r_u,
if (!prs_uint32("ptr_info", ps, depth, &r_u->ptr_info))
return False;
+ /* special case: Windows 2000 can return stub data here saying
+ NT_STATUS_NOT_SUPPORTED */
+
+ if ( NT_STATUS_EQUAL( NT_STATUS_NOT_SUPPORTED, NT_STATUS(r_u->ptr_info)) ) {
+ r_u->status = NT_STATUS_NOT_SUPPORTED;
+ return True;
+ }
+
if (r_u->ptr_info && r_u->info != NULL) {
/* SAM_UNK_INFO_1 */
if (!sam_io_unk_info1("info", r_u->info, ps, depth))
diff --git a/source/rpc_parse/parse_sec.c b/source/rpc_parse/parse_sec.c
index 6a752688a0b..76583605939 100644
--- a/source/rpc_parse/parse_sec.c
+++ b/source/rpc_parse/parse_sec.c
@@ -28,24 +28,6 @@
#define DBGC_CLASS DBGC_RPC_PARSE
/*******************************************************************
- Reads or writes a SEC_ACCESS structure.
-********************************************************************/
-
-BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
-{
- if (t == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "sec_io_access");
- depth++;
-
- if(!prs_uint32("mask", ps, depth, &t->mask))
- return False;
-
- return True;
-}
-
-/*******************************************************************
Reads or writes a SEC_ACE structure.
********************************************************************/
@@ -71,7 +53,7 @@ BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
return False;
- if(!sec_io_access("info ", &psa->info, ps, depth))
+ if (!prs_uint32("access_mask", ps, depth, &psa->access_mask))
return False;
/* check whether object access is present */
@@ -170,14 +152,14 @@ BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
* between a non-present DACL (allow all access) and a DACL with no ACE's
* (allow no access).
*/
- if((psa->ace = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces+1)) == NULL)
+ if((psa->aces = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces+1)) == NULL)
return False;
}
for (i = 0; i < psa->num_aces; i++) {
fstring tmp;
slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
- if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
+ if(!sec_io_ace(tmp, &psa->aces[i], ps, depth))
return False;
}
@@ -270,9 +252,9 @@ BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
psd->off_owner_sid = 0;
}
- if (psd->grp_sid != NULL) {
+ if (psd->group_sid != NULL) {
psd->off_grp_sid = offset;
- offset += sid_size(psd->grp_sid);
+ offset += sid_size(psd->group_sid);
} else {
psd->off_grp_sid = 0;
}
@@ -321,11 +303,11 @@ BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
if (UNMARSHALLING(ps)) {
/* reading */
- if((psd->grp_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL)
+ if((psd->group_sid = PRS_ALLOC_MEM(ps,DOM_SID,1)) == NULL)
return False;
}
- if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
+ if(!smb_io_dom_sid("group_sid", psd->group_sid, ps, depth))
return False;
max_offset = MAX(max_offset, prs_offset(ps));
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index 2884883e893..90c47950af7 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -3,7 +3,7 @@
* 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) Jean François Micouleau 1998-2000,
* Copyright (C) Gerald Carter 2000-2002,
* Copyright (C) Tim Potter 2001-2002.
*
@@ -606,7 +606,7 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc
switch ( q_u->level )
{
case 1:
- if ( !prs_pointer( "" , ps, depth, (void**)&q_u->user.user1,
+ if ( !prs_pointer( "" , ps, depth, (void*)&q_u->user.user1,
sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 ))
{
return False;
@@ -2452,6 +2452,24 @@ BOOL smb_io_printer_info_5(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_5
}
/*******************************************************************
+ Parse a PRINTER_INFO_6 structure.
+********************************************************************/
+
+BOOL smb_io_printer_info_6(const char *desc, RPC_BUFFER *buffer,
+ PRINTER_INFO_6 *info, int depth)
+{
+ prs_struct *ps=&buffer->prs;
+
+ prs_debug(ps, depth, desc, "smb_io_printer_info_6");
+ depth++;
+
+ if (!prs_uint32("status", ps, depth, &info->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
Parse a PRINTER_INFO_7 structure.
********************************************************************/
@@ -2643,9 +2661,7 @@ BOOL smb_io_printer_driver_info_6(const char *desc, RPC_BUFFER *buffer, DRIVER_I
if (!smb_io_relarraystr("previousdrivernames", buffer, depth, &info->previousdrivernames))
return False;
- if (!prs_uint32("date.low", ps, depth, &info->driver_date.low))
- return False;
- if (!prs_uint32("date.high", ps, depth, &info->driver_date.high))
+ if (!prs_uint64("date", ps, depth, &info->driver_date))
return False;
if (!prs_uint32("padding", ps, depth, &info->padding))
@@ -3112,6 +3128,14 @@ uint32 spoolss_size_printer_info_5(PRINTER_INFO_5 *info)
return size;
}
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/
+
+uint32 spoolss_size_printer_info_6(PRINTER_INFO_6 *info)
+{
+ return sizeof(uint32);
+}
/*******************************************************************
return the size required by a struct in the stream
@@ -3893,7 +3917,16 @@ BOOL spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_stru
}
case 3:
{
- ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
+ /* FIXME ! Our parsing here is wrong I think,
+ * but for a level3 it makes no sense for
+ * ptr_sec_desc to be NULL. JRA. Based on
+ * a Vista sniff from Martin Zielinski <mz@seh.de>.
+ */
+ if (UNMARSHALLING(ps)) {
+ ptr_sec_desc = 1;
+ } else {
+ ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
+ }
break;
}
}
@@ -3910,8 +3943,8 @@ BOOL spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_stru
prs_debug(ps, depth, "", "sec_io_desc_buf");
if (!prs_uint32("size", ps, depth + 1, &dummy))
return False;
- if (!prs_uint32("ptr", ps, depth + 1, &dummy)) return
- False;
+ if (!prs_uint32("ptr", ps, depth + 1, &dummy))
+ return False;
}
if(!prs_uint32("command", ps, depth, &q_u->command))
@@ -6269,6 +6302,11 @@ void free_printer_info_5(PRINTER_INFO_5 *printer)
SAFE_FREE(printer);
}
+void free_printer_info_6(PRINTER_INFO_6 *printer)
+{
+ SAFE_FREE(printer);
+}
+
void free_printer_info_7(PRINTER_INFO_7 *printer)
{
SAFE_FREE(printer);
diff --git a/source/rpc_parse/parse_svcctl.c b/source/rpc_parse/parse_svcctl.c
index 2cb44c63195..dc4ee3e6e99 100644
--- a/source/rpc_parse/parse_svcctl.c
+++ b/source/rpc_parse/parse_svcctl.c
@@ -257,12 +257,12 @@ BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u,
if(!prs_align(ps))
return False;
- if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+ 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))
+ 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;
@@ -486,7 +486,7 @@ BOOL svcctl_io_q_enum_services_status(const char *desc, SVCCTL_Q_ENUM_SERVICES_S
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))
+ if(!prs_pointer("resume", ps, depth, (void*)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32))
return False;
return True;
@@ -517,7 +517,7 @@ BOOL svcctl_io_r_enum_services_status(const char *desc, SVCCTL_R_ENUM_SERVICES_S
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))
+ 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))
@@ -546,7 +546,7 @@ BOOL svcctl_io_q_start_service(const char *desc, SVCCTL_Q_START_SERVICE *q_u, pr
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) )
+ if ( !prs_pointer("rights", ps, depth, (void*)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) )
return False;
return True;
@@ -821,9 +821,9 @@ BOOL svcctl_io_service_fa( const char *desc, SERVICE_FAILURE_ACTIONS *fa, RPC_BU
if ( !prs_uint32("reset_period", ps, depth, &fa->reset_period) )
return False;
- if ( !prs_pointer( desc, ps, depth, (void**)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+ if ( !prs_pointer( desc, ps, depth, (void*)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
return False;
- if ( !prs_pointer( desc, ps, depth, (void**)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+ if ( !prs_pointer( desc, ps, depth, (void*)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
return False;
if ( !prs_uint32("num_actions", ps, depth, &fa->num_actions) )
diff --git a/source/rpc_parse/parse_wks.c b/source/rpc_parse/parse_wks.c
deleted file mode 100644
index b6de058652b..00000000000
--- a/source/rpc_parse/parse_wks.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- *
- * 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
-
-/*******************************************************************
- Init
- ********************************************************************/
-
-void init_wks_q_query_info(WKS_Q_QUERY_INFO *q_u,
- char *server, uint16 switch_value)
-{
- DEBUG(5,("init_wks_q_query_info\n"));
-
- init_buf_unistr2(&q_u->uni_srv_name, &q_u->ptr_srv_name, server);
- q_u->switch_value = switch_value;
-}
-
-/*******************************************************************
- Reads or writes a WKS_Q_QUERY_INFO structure.
-********************************************************************/
-
-BOOL wks_io_q_query_info(const char *desc, WKS_Q_QUERY_INFO *q_u, prs_struct *ps, int depth)
-{
- if (q_u == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "wks_io_q_query_info");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name))
- return False;
- if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth))
- return False;
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint16("switch_value", ps, depth, &q_u->switch_value))
- return False;
- if(!prs_align(ps))
- return False;
-
- return True;
-}
-
-/*******************************************************************
- wks_info_100
- ********************************************************************/
-
-void init_wks_info_100(WKS_INFO_100 *inf,
- uint32 platform_id, uint32 ver_major, uint32 ver_minor,
- char *my_name, char *domain_name)
-{
- DEBUG(5,("Init WKS_INFO_100: %d\n", __LINE__));
-
- inf->platform_id = platform_id; /* 0x0000 01f4 - unknown */
- inf->ver_major = ver_major; /* os major version */
- inf->ver_minor = ver_minor; /* os minor version */
-
- init_buf_unistr2(&inf->uni_compname, &inf->ptr_compname, my_name );
- init_buf_unistr2(&inf->uni_lan_grp, &inf->ptr_lan_grp, domain_name);
-}
-
-/*******************************************************************
- Reads or writes a WKS_INFO_100 structure.
-********************************************************************/
-
-static BOOL wks_io_wks_info_100(const char *desc, WKS_INFO_100 *inf, prs_struct *ps, int depth)
-{
- if (inf == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "wks_io_wks_info_100");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("platform_id ", ps, depth, &inf->platform_id)) /* 0x0000 01f4 - unknown */
- return False;
- if(!prs_uint32("ptr_compname", ps, depth, &inf->ptr_compname)) /* pointer to computer name */
- return False;
- if(!prs_uint32("ptr_lan_grp ", ps, depth, &inf->ptr_lan_grp)) /* pointer to LAN group name */
- return False;
- if(!prs_uint32("ver_major ", ps, depth, &inf->ver_major)) /* 4 - major os version */
- return False;
- if(!prs_uint32("ver_minor ", ps, depth, &inf->ver_minor)) /* 0 - minor os version */
- return False;
-
- if(!smb_io_unistr2("", &inf->uni_compname, inf->ptr_compname, ps, depth))
- return False;
- if(!prs_align(ps))
- return False;
-
- if(!smb_io_unistr2("", &inf->uni_lan_grp, inf->ptr_lan_grp , ps, depth))
- return False;
- if(!prs_align(ps))
- return False;
-
- return True;
-}
-
-/*******************************************************************
- Inits WKS_R_QUERY_INFO.
-
- only supports info level 100 at the moment.
-
- ********************************************************************/
-
-void init_wks_r_query_info(WKS_R_QUERY_INFO *r_u,
- uint32 switch_value, WKS_INFO_100 *wks100,
- NTSTATUS status)
-{
- DEBUG(5,("init_wks_r_unknown_0: %d\n", __LINE__));
-
- r_u->switch_value = switch_value; /* same as in request */
-
- r_u->ptr_1 = 1; /* pointer 1 */
- r_u->wks100 = wks100;
-
- r_u->status = status;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-BOOL wks_io_r_query_info(const char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth)
-{
- if (r_u == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "wks_io_r_query_info");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint16("switch_value", ps, depth, &r_u->switch_value)) /* level 100 (0x64) */
- return False;
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("ptr_1 ", ps, depth, &r_u->ptr_1)) /* pointer 1 */
- return False;
- if(!wks_io_wks_info_100("inf", r_u->wks100, ps, depth))
- return False;
-
- if(!prs_ntstatus("status ", ps, depth, &r_u->status))
- return False;
-
- return True;
-}
diff --git a/source/rpc_server/srv_eventlog_lib.c b/source/rpc_server/srv_eventlog_lib.c
index 66be1dc34ff..37b759ecf2a 100644
--- a/source/rpc_server/srv_eventlog_lib.c
+++ b/source/rpc_server/srv_eventlog_lib.c
@@ -486,7 +486,7 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
}
/* alloc mem for the packed version */
- packed_ee = TALLOC( mem_ctx, ee->record.length + MARGIN );
+ packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN );
if ( !packed_ee ) {
talloc_destroy( mem_ctx );
return 0;
diff --git a/source/rpc_server/srv_eventlog_nt.c b/source/rpc_server/srv_eventlog_nt.c
index 79839a0a52a..06842760154 100644
--- a/source/rpc_server/srv_eventlog_nt.c
+++ b/source/rpc_server/srv_eventlog_nt.c
@@ -281,7 +281,7 @@ static int elog_size( EVENTLOG_INFO *info )
Eventlog_entry. returns NULL if it can't get the record for some reason.
********************************************************************/
-Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
+static Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
int recno, Eventlog_entry * ee )
{
TDB_DATA ret, key;
diff --git a/source/rpc_server/srv_lsa_hnd.c b/source/rpc_server/srv_lsa_hnd.c
index 7da87d5b93d..88c59ee8952 100644
--- a/source/rpc_server/srv_lsa_hnd.c
+++ b/source/rpc_server/srv_lsa_hnd.c
@@ -103,6 +103,7 @@ BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
{
static uint32 pol_hnd_low = 0;
static uint32 pol_hnd_high = 0;
+ time_t t = time(NULL);
struct policy *pol;
@@ -127,12 +128,17 @@ BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
if (pol_hnd_low == 0)
(pol_hnd_high)++;
- SIVAL(&pol->pol_hnd.data1, 0 , 0); /* first bit must be null */
- SIVAL(&pol->pol_hnd.data2, 0 , pol_hnd_low ); /* second bit is incrementing */
- SSVAL(&pol->pol_hnd.data3, 0 , pol_hnd_high); /* second bit is incrementing */
- SSVAL(&pol->pol_hnd.data4, 0 , (pol_hnd_high>>16)); /* second bit is incrementing */
- SIVAL(pol->pol_hnd.data5, 0, time(NULL)); /* something random */
- SIVAL(pol->pol_hnd.data5, 4, sys_getpid()); /* something more random */
+ SIVAL(&pol->pol_hnd.handle_type, 0 , 0); /* first bit must be null */
+ SIVAL(&pol->pol_hnd.uuid.time_low, 0 , pol_hnd_low ); /* second bit is incrementing */
+ SSVAL(&pol->pol_hnd.uuid.time_mid, 0 , pol_hnd_high); /* second bit is incrementing */
+ SSVAL(&pol->pol_hnd.uuid.time_hi_and_version, 0 , (pol_hnd_high>>16)); /* second bit is incrementing */
+
+ /* split the current time into two 16 bit values */
+
+ SSVAL(pol->pol_hnd.uuid.clock_seq, 0, (t>>16)); /* something random */
+ SSVAL(pol->pol_hnd.uuid.node, 0, t); /* something random */
+
+ SIVAL(pol->pol_hnd.uuid.node, 2, sys_getpid()); /* something more random */
DLIST_ADD(p->pipe_handles->Policy, pol);
p->pipe_handles->count++;
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index 010c35e3fff..3e39b2fd831 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -164,7 +164,7 @@ static NTSTATUS lookup_lsa_rids(TALLOC_CTX *mem_ctx,
int dom_idx;
char *full_name;
const char *domain;
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
+ enum lsa_SidType type = SID_NAME_UNKNOWN;
/* Split name into domain and user component */
@@ -239,7 +239,7 @@ static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx,
int dom_idx;
char *full_name;
const char *domain;
- enum SID_NAME_USE type = SID_NAME_UNKNOWN;
+ enum lsa_SidType type = SID_NAME_UNKNOWN;
/* Split name into domain and user component */
@@ -487,7 +487,7 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s
static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
const char *dns_name, const char *forest_name,
- struct uuid *dom_guid, DOM_SID *dom_sid)
+ struct GUID *dom_guid, DOM_SID *dom_sid)
{
if (nb_name && *nb_name) {
init_unistr2(&r_l->uni_nb_dom_name, nb_name, UNI_FLAGS_NONE);
@@ -512,7 +512,7 @@ static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
/* how do we init the guid ? probably should write an init fn */
if (dom_guid) {
- memcpy(&r_l->dom_guid, dom_guid, sizeof(struct uuid));
+ memcpy(&r_l->dom_guid, dom_guid, sizeof(struct GUID));
}
if (dom_sid) {
@@ -1866,7 +1866,7 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I
char *dns_name = NULL;
char *forest_name = NULL;
DOM_SID *sid = NULL;
- struct uuid guid;
+ struct GUID guid;
fstring dnsdomname;
ZERO_STRUCT(guid);
diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c
index 6603d2f1d44..b8c776964e9 100644
--- a/source/rpc_server/srv_netlog_nt.c
+++ b/source/rpc_server/srv_netlog_nt.c
@@ -623,7 +623,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_pass_changed_now(sampass)) {
+ if (!pdb_set_pass_last_set_time(sampass, time(NULL), PDB_CHANGED)) {
TALLOC_FREE(sampass);
/* Not quite sure what this one qualifies as, but this will do */
return NT_STATUS_UNSUCCESSFUL;
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index b4787f652df..db1c3fea0e5 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -990,9 +990,9 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
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)
+ && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct GUID)) == 0)
&& (transfer->version == pipe_names[i].trans_syntax.version)
- && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) {
+ && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct GUID)) == 0) ) {
struct api_struct *fns = NULL;
int n_fns = 0;
PIPE_RPC_FNS *context_fns;
diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c
index 8fd0e55c547..3728252c993 100644
--- a/source/rpc_server/srv_reg_nt.c
+++ b/source/rpc_server/srv_reg_nt.c
@@ -30,9 +30,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
-#define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
-((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
-
static struct generic_mapping reg_generic_map =
{ REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index b8d4f072aee..07a89de5e61 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -40,12 +40,12 @@
( READ_CONTROL_ACCESS | \
SA_RIGHT_USER_CHANGE_PASSWORD | \
SA_RIGHT_USER_SET_LOC_COM )
+#define SAMR_USR_RIGHTS_CANT_WRITE_PW \
+ ( READ_CONTROL_ACCESS | SA_RIGHT_USER_SET_LOC_COM )
#define DISP_INFO_CACHE_TIMEOUT 10
typedef struct disp_info {
- struct disp_info *next, *prev;
- TALLOC_CTX *mem_ctx;
DOM_SID sid; /* identify which domain this is. */
BOOL builtin_domain; /* Quick flag to check if this is the builtin domain. */
struct pdb_search *users; /* querydispinfo 1 and 4 */
@@ -63,8 +63,6 @@ typedef struct disp_info {
/* We keep a static list of these by SID as modern clients close down
all resources between each request in a complete enumeration. */
-static DISP_INFO *disp_info_list;
-
struct samr_info {
/* for use by the \PIPE\samr policy */
DOM_SID sid;
@@ -90,6 +88,11 @@ static struct generic_mapping usr_generic_mapping = {
GENERIC_RIGHTS_USER_WRITE,
GENERIC_RIGHTS_USER_EXECUTE,
GENERIC_RIGHTS_USER_ALL_ACCESS};
+static struct generic_mapping usr_nopwchange_generic_mapping = {
+ GENERIC_RIGHTS_USER_READ,
+ GENERIC_RIGHTS_USER_WRITE,
+ GENERIC_RIGHTS_USER_EXECUTE & ~SA_RIGHT_USER_CHANGE_PASSWORD,
+ GENERIC_RIGHTS_USER_ALL_ACCESS};
static struct generic_mapping grp_generic_mapping = {
GENERIC_RIGHTS_GROUP_READ,
GENERIC_RIGHTS_GROUP_WRITE,
@@ -247,49 +250,59 @@ static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_requir
Fetch or create a dispinfo struct.
********************************************************************/
-static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid, const char *sid_str)
+static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid)
{
- TALLOC_CTX *mem_ctx;
- DISP_INFO *dpi;
+ /*
+ * We do a static cache for DISP_INFO's here. Explanation can be found
+ * in Jeremy's checkin message to r11793:
+ *
+ * Fix the SAMR cache so it works across completely insane
+ * client behaviour (ie.:
+ * open pipe/open SAMR handle/enumerate 0 - 1024
+ * close SAMR handle, close pipe.
+ * open pipe/open SAMR handle/enumerate 1024 - 2048...
+ * close SAMR handle, close pipe.
+ * And on ad-nausium. Amazing.... probably object-oriented
+ * client side programming in action yet again.
+ * This change should *massively* improve performance when
+ * enumerating users from an LDAP database.
+ * Jeremy.
+ *
+ * "Our" and the builtin domain are the only ones where we ever
+ * enumerate stuff, so just cache 2 entries.
+ */
+
+ static struct disp_info builtin_dispinfo;
+ static struct disp_info domain_dispinfo;
/* There are two cases to consider here:
1) The SID is a domain SID and we look for an equality match, or
2) This is an account SID and so we return the DISP_INFO* for our
domain */
- if ( psid && sid_check_is_in_our_domain( psid ) ) {
- DEBUG(10,("get_samr_dispinfo_by_sid: Replacing %s with our domain SID\n",
- sid_str));
- psid = get_global_sam_sid();
- }
-
- for (dpi = disp_info_list; dpi; dpi = dpi->next) {
- if (sid_equal(psid, &dpi->sid)) {
- return dpi;
- }
- }
-
- /* This struct is never free'd - I'm using talloc so we
- can get a list out of smbd using smbcontrol. There will
- be one of these per SID we're authorative for. JRA. */
-
- mem_ctx = talloc_init("DISP_INFO for domain sid %s", sid_str);
-
- if ((dpi = TALLOC_ZERO_P(mem_ctx, DISP_INFO)) == NULL)
+ if (psid == NULL) {
return NULL;
+ }
- dpi->mem_ctx = mem_ctx;
+ if (sid_check_is_builtin(psid) || sid_check_is_in_builtin(psid)) {
+ /*
+ * Necessary only once, but it does not really hurt.
+ */
+ sid_copy(&builtin_dispinfo.sid, &global_sid_Builtin);
- if (psid) {
- sid_copy( &dpi->sid, psid);
- dpi->builtin_domain = sid_check_is_builtin(psid);
- } else {
- dpi->builtin_domain = False;
+ return &builtin_dispinfo;
}
+
+ if (sid_check_is_domain(psid) || sid_check_is_in_our_domain(psid)) {
+ /*
+ * Necessary only once, but it does not really hurt.
+ */
+ sid_copy(&domain_dispinfo.sid, get_global_sam_sid());
- DLIST_ADD(disp_info_list, dpi);
+ return &domain_dispinfo;
+ }
- return dpi;
+ return NULL;
}
/*******************************************************************
@@ -323,12 +336,7 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
}
info->mem_ctx = mem_ctx;
- info->disp_info = get_samr_dispinfo_by_sid(psid, sid_str);
-
- if (!info->disp_info) {
- talloc_destroy(mem_ctx);
- return NULL;
- }
+ info->disp_info = get_samr_dispinfo_by_sid(psid);
return info;
}
@@ -657,16 +665,6 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
}
/*******************************************************************
- _samr_set_sec_obj
- ********************************************************************/
-
-NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u)
-{
- DEBUG(0,("_samr_set_sec_obj: Not yet implemented!\n"));
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/*******************************************************************
********************************************************************/
static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol,
@@ -692,6 +690,97 @@ static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol,
}
/*******************************************************************
+ _samr_set_sec_obj
+ ********************************************************************/
+
+NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u)
+{
+ DOM_SID pol_sid;
+ uint32 acc_granted, i;
+ SEC_ACL *dacl;
+ BOOL ret;
+ struct samu *sampass=NULL;
+ NTSTATUS status;
+
+ r_u->status = NT_STATUS_OK;
+
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL))
+ return NT_STATUS_INVALID_HANDLE;
+
+ if (!(sampass = samu_new( p->mem_ctx))) {
+ DEBUG(0,("No memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* get the user record */
+ become_root();
+ ret = pdb_getsampwsid(sampass, &pol_sid);
+ unbecome_root();
+
+ if (!ret) {
+ DEBUG(4, ("User %s not found\n", sid_string_static(&pol_sid)));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ dacl = q_u->buf->sec->dacl;
+ for (i=0; i < dacl->num_aces; i++) {
+ if (sid_equal(&pol_sid, &dacl->aces[i].trustee)) {
+ ret = pdb_set_pass_can_change(sampass,
+ (dacl->aces[i].access_mask &
+ SA_RIGHT_USER_CHANGE_PASSWORD) ?
+ True: False);
+ break;
+ }
+ }
+
+ if (!ret) {
+ TALLOC_FREE(sampass);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ status = pdb_update_sam_account(sampass);
+
+ TALLOC_FREE(sampass);
+
+ return status;
+}
+
+/*******************************************************************
+ build correct perms based on policies and password times for _samr_query_sec_obj
+*******************************************************************/
+static BOOL check_change_pw_access(TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
+{
+ struct samu *sampass=NULL;
+ BOOL ret;
+
+ if ( !(sampass = samu_new( mem_ctx )) ) {
+ DEBUG(0,("No memory!\n"));
+ return False;
+ }
+
+ become_root();
+ ret = pdb_getsampwsid(sampass, user_sid);
+ unbecome_root();
+
+ if (ret == False) {
+ DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
+ TALLOC_FREE(sampass);
+ return False;
+ }
+
+ DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) ));
+
+ if (pdb_get_pass_can_change(sampass)) {
+ TALLOC_FREE(sampass);
+ return True;
+ }
+ TALLOC_FREE(sampass);
+ return False;
+}
+
+
+/*******************************************************************
_samr_query_sec_obj
********************************************************************/
@@ -731,7 +820,13 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
/* TODO: different SDs have to be generated for aliases groups and users.
Currently all three get a default user SD */
DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
- r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &pol_sid, SAMR_USR_RIGHTS_WRITE_PW);
+ if (check_change_pw_access(p->mem_ctx, &pol_sid)) {
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping,
+ &pol_sid, SAMR_USR_RIGHTS_WRITE_PW);
+ } else {
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_nopwchange_generic_mapping,
+ &pol_sid, SAMR_USR_RIGHTS_CANT_WRITE_PW);
+ }
} else {
return NT_STATUS_OBJECT_TYPE_MISMATCH;
}
@@ -1377,7 +1472,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM
NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u)
{
uint32 rid[MAX_SAM_ENTRIES];
- enum SID_NAME_USE type[MAX_SAM_ENTRIES];
+ enum lsa_SidType type[MAX_SAM_ENTRIES];
int i;
int num_rids = q_u->num_names2;
DOM_SID pol_sid;
@@ -1435,7 +1530,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
}
}
- init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
+ init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status);
DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
@@ -1618,12 +1713,14 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names,
NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u)
{
const char **names;
- uint32 *attrs = NULL;
+ enum lsa_SidType *attrs = NULL;
+ uint32 *wire_attrs = NULL;
UNIHDR *hdr_name = NULL;
UNISTR2 *uni_name = NULL;
DOM_SID pol_sid;
int num_rids = q_u->num_rids1;
uint32 acc_granted;
+ int i;
r_u->status = NT_STATUS_OK;
@@ -1640,9 +1737,10 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
}
names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids);
- attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
+ attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, enum lsa_SidType, num_rids);
+ wire_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
- if ((num_rids != 0) && ((names == NULL) || (attrs == NULL)))
+ if ((num_rids != 0) && ((names == NULL) || (attrs == NULL) || (wire_attrs==NULL)))
return NT_STATUS_NO_MEMORY;
become_root(); /* lookup_sid can require root privs */
@@ -1658,7 +1756,12 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
&hdr_name, &uni_name))
return NT_STATUS_NO_MEMORY;
- init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, attrs);
+ /* Convert from enum lsa_SidType to uint32 for wire format. */
+ for (i = 0; i < num_rids; i++) {
+ wire_attrs[i] = (uint32)attrs[i];
+ }
+
+ init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, wire_attrs);
DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
@@ -2077,6 +2180,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
uint32 acc_granted;
BOOL ret;
NTSTATUS result;
+ BOOL success = False;
/*
* from the SID in the request:
@@ -2121,9 +2225,15 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
sids = NULL;
+ /* make both calls inside the root block */
become_root();
result = pdb_enum_group_memberships(p->mem_ctx, sam_pass,
&sids, &unix_gids, &num_groups);
+ if ( NT_STATUS_IS_OK(result) ) {
+ success = sid_peek_check_rid(get_global_sam_sid(),
+ pdb_get_group_sid(sam_pass),
+ &primary_group_rid);
+ }
unbecome_root();
if (!NT_STATUS_IS_OK(result)) {
@@ -2132,15 +2242,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
return result;
}
- gids = NULL;
- num_gids = 0;
-
- dom_gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
- SE_GROUP_ENABLED);
-
- if (!sid_peek_check_rid(get_global_sam_sid(),
- pdb_get_group_sid(sam_pass),
- &primary_group_rid)) {
+ if ( !success ) {
DEBUG(5, ("Group sid %s for user %s not in our domain\n",
sid_string_static(pdb_get_group_sid(sam_pass)),
pdb_get_username(sam_pass)));
@@ -2148,8 +2250,12 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- dom_gid.g_rid = primary_group_rid;
+ gids = NULL;
+ num_gids = 0;
+ dom_gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
+ SE_GROUP_ENABLED);
+ dom_gid.g_rid = primary_group_rid;
ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids);
for (i=0; i<num_groups; i++) {
@@ -2383,7 +2489,7 @@ NTSTATUS _samr_query_domain_info(pipes_struct *p,
static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name)
{
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
BOOL result;
DEBUG(10, ("Checking whether [%s] can be created\n", new_name));
@@ -2498,7 +2604,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
}
DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
- p->pipe_user_name, can_add_account ? "True":"False" ));
+ uidtoname(p->pipe_user.ut.uid),
+ can_add_account ? "True":"False" ));
/********** BEGIN Admin BLOCK **********/
@@ -2924,7 +3031,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
{
/* Check we actually have the requested alias */
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
BOOL result;
gid_t gid;
@@ -3047,7 +3154,7 @@ static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, struct samu *pwd)
TALLOC_FREE(pwd);
return False;
}
- if (!pdb_set_pass_changed_now (pwd)) {
+ if (!pdb_set_pass_last_set_time (pwd, time(NULL), PDB_CHANGED)) {
TALLOC_FREE(pwd);
return False;
}
@@ -3100,9 +3207,11 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
}
/* we need to separately check for an account rename first */
+
if (rpcstr_pull(new_name, id21->uni_user_name.buffer,
- sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) &&
- (!strequal(new_name, pdb_get_username(pwd)))) {
+ sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0)
+ && (!strequal(new_name, pdb_get_username(pwd))))
+ {
/* check to see if the new username already exists. Note: we can't
reliably lock all backends, so there is potentially the
@@ -3327,11 +3436,18 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25,
copy_id25_to_sam_passwd(pwd, id25);
+ /* write the change out */
+ if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
+ return status;
+ }
+
/*
- * The funny part about the previous two calls is
- * that pwd still has the password hashes from the
- * passdb entry. These have not been updated from
- * id21. I don't know if they need to be set. --jerry
+ * We need to "pdb_update_sam_account" before the unix primary group
+ * is set, because the idealx scripts would also change the
+ * sambaPrimaryGroupSid using the ldap replace method. pdb_ldap uses
+ * the delete explicit / add explicit, which would then fail to find
+ * the previous primaryGroupSid value.
*/
if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) {
@@ -3341,16 +3457,6 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25,
}
}
- /* Don't worry about writing out the user account since the
- primary group SID is generated solely from the user's Unix
- primary group. */
-
- /* write the change out */
- if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
- TALLOC_FREE(pwd);
- return status;
- }
-
/* WARNING: No TALLOC_FREE(pwd), we are about to set the password
* hereafter! */
@@ -3440,7 +3546,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
}
DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
- p->pipe_user_name, has_enough_rights ? "" : " not"));
+ uidtoname(p->pipe_user.ut.uid),
+ has_enough_rights ? "" : " not"));
/* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
@@ -3598,7 +3705,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
}
DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n",
- p->pipe_user_name, has_enough_rights ? "" : " not"));
+ uidtoname(p->pipe_user.ut.uid),
+ has_enough_rights ? "" : " not"));
/* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
@@ -4601,6 +4709,10 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
switch (ctr->level) {
case 2:
+ {
+ fstring group_name, acct_name;
+ NTSTATUS status;
+
/* We currently do not support renaming groups in the
the BUILTIN domain. Refer to util_builtin.c to understand
why. The eventually needs to be fixed to be like Windows
@@ -4610,13 +4722,31 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
return NT_STATUS_SPECIAL_ACCOUNT;
}
- if ( ctr->alias.info2.name.string ) {
- unistr2_to_ascii( info.acct_name, ctr->alias.info2.name.string,
- sizeof(info.acct_name)-1 );
- }
- else
- fstrcpy( info.acct_name, "" );
+ /* There has to be a valid name (and it has to be different) */
+
+ if ( !ctr->alias.info2.name.string )
+ return NT_STATUS_INVALID_PARAMETER;
+
+ unistr2_to_ascii( acct_name, ctr->alias.info2.name.string,
+ sizeof(acct_name)-1 );
+
+ /* If the name is the same just reply "ok". Yes this
+ doesn't allow you to change the case of a group name. */
+
+ if ( strequal( acct_name, info.acct_name ) )
+ return NT_STATUS_OK;
+
+ fstrcpy( info.acct_name, acct_name );
+
+ /* make sure the name doesn't already exist as a user
+ or local group */
+
+ fstr_sprintf( group_name, "%s\\%s", global_myname(), info.acct_name );
+ status = can_create( p->mem_ctx, group_name );
+ if ( !NT_STATUS_IS_OK( status ) )
+ return status;
break;
+ }
case 3:
if ( ctr->alias.info3.description.string ) {
unistr2_to_ascii( info.acct_desc,
diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c
index 2b65eb210fd..8acc1785ef6 100644
--- a/source/rpc_server/srv_samr_util.c
+++ b/source/rpc_server/srv_samr_util.c
@@ -52,6 +52,7 @@ void copy_id20_to_sam_passwd(struct samu *to, SAM_USER_INFO_20 *from)
old_string = pdb_get_munged_dial(to);
mung.length = from->hdr_munged_dial.uni_str_len;
mung.data = (uint8 *) from->uni_munged_dial.buffer;
+ mung.free = NULL;
new_string = (mung.length == 0) ?
NULL : base64_encode_data_blob(mung);
DEBUG(10,("INFO_20 UNI_MUNGED_DIAL: %s -> %s\n",old_string, new_string));
@@ -76,7 +77,7 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
return;
if (from->fields_present & ACCT_LAST_LOGON) {
- unix_time=nt_time_to_unix(&from->logon_time);
+ unix_time=nt_time_to_unix(from->logon_time);
stored_time = pdb_get_logon_time(to);
DEBUG(10,("INFO_21 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -84,7 +85,7 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
}
if (from->fields_present & ACCT_LAST_LOGOFF) {
- unix_time=nt_time_to_unix(&from->logoff_time);
+ unix_time=nt_time_to_unix(from->logoff_time);
stored_time = pdb_get_logoff_time(to);
DEBUG(10,("INFO_21 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -92,37 +93,21 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
}
if (from->fields_present & ACCT_EXPIRY) {
- unix_time=nt_time_to_unix(&from->kickoff_time);
+ unix_time=nt_time_to_unix(from->kickoff_time);
stored_time = pdb_get_kickoff_time(to);
DEBUG(10,("INFO_21 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
}
- if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_can_change_time);
- stored_time = pdb_get_pass_can_change_time(to);
- DEBUG(10,("INFO_21 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
- }
-
if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_last_set_time);
+ unix_time=nt_time_to_unix(from->pass_last_set_time);
stored_time = pdb_get_pass_last_set_time(to);
DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
}
- if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_must_change_time);
- stored_time=pdb_get_pass_must_change_time(to);
- DEBUG(10,("INFO_21 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
- }
-
if ((from->fields_present & ACCT_USERNAME) &&
(from->hdr_user_name.buffer)) {
old_string = pdb_get_username(to);
@@ -195,14 +180,13 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
pdb_set_workstations(to , new_string, PDB_CHANGED);
}
- /* is this right? */
- if ((from->fields_present & ACCT_ADMIN_DESC) &&
- (from->hdr_unknown_str.buffer)) {
- old_string = pdb_get_unknown_str(to);
- new_string = unistr2_static(&from->uni_unknown_str);
- DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
+ if ((from->fields_present & ACCT_COMMENT) &&
+ (from->hdr_comment.buffer)) {
+ old_string = pdb_get_comment(to);
+ new_string = unistr2_static(&from->uni_comment);
+ DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string));
if (STRING_CHANGED)
- pdb_set_unknown_str(to , new_string, PDB_CHANGED);
+ pdb_set_comment(to, new_string, PDB_CHANGED);
}
if ((from->fields_present & ACCT_CALLBACK) &&
@@ -211,6 +195,7 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
old_string = pdb_get_munged_dial(to);
mung.length = from->hdr_munged_dial.uni_str_len;
mung.data = (uint8 *) from->uni_munged_dial.buffer;
+ mung.free = NULL;
newstr = (mung.length == 0) ?
NULL : base64_encode_data_blob(mung);
DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
@@ -284,26 +269,16 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
}
}
- DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
- if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) {
- pdb_set_pass_must_change_time(to,0, PDB_CHANGED);
- } else {
- uint32 expire;
- time_t new_time;
- if (pdb_get_pass_must_change_time(to) == 0) {
- if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
- || expire == (uint32)-1) {
- new_time = get_time_t_max();
- } else {
- time_t old_time = pdb_get_pass_last_set_time(to);
- new_time = old_time + expire;
- if ((new_time) < time(0)) {
- new_time = time(0) + expire;
- }
- }
- if (!pdb_set_pass_must_change_time (to, new_time, PDB_CHANGED)) {
- DEBUG (0, ("pdb_set_pass_must_change_time failed!\n"));
- }
+ /* If the must change flag is set, the last set time goes to zero.
+ the must change and can change fields also do, but they are
+ calculated from policy, not set from the wire */
+
+ if (from->fields_present & ACCT_EXPIRED_FLAG) {
+ DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
+ if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
+ pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
+ } else {
+ pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
}
}
@@ -325,7 +300,7 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
return;
if (from->fields_present & ACCT_LAST_LOGON) {
- unix_time=nt_time_to_unix(&from->logon_time);
+ unix_time=nt_time_to_unix(from->logon_time);
stored_time = pdb_get_logon_time(to);
DEBUG(10,("INFO_23 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -333,7 +308,7 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
}
if (from->fields_present & ACCT_LAST_LOGOFF) {
- unix_time=nt_time_to_unix(&from->logoff_time);
+ unix_time=nt_time_to_unix(from->logoff_time);
stored_time = pdb_get_logoff_time(to);
DEBUG(10,("INFO_23 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -341,37 +316,21 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
}
if (from->fields_present & ACCT_EXPIRY) {
- unix_time=nt_time_to_unix(&from->kickoff_time);
+ unix_time=nt_time_to_unix(from->kickoff_time);
stored_time = pdb_get_kickoff_time(to);
DEBUG(10,("INFO_23 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
}
- if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_can_change_time);
- stored_time = pdb_get_pass_can_change_time(to);
- DEBUG(10,("INFO_23 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
- }
-
if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_last_set_time);
+ unix_time=nt_time_to_unix(from->pass_last_set_time);
stored_time = pdb_get_pass_last_set_time(to);
DEBUG(10,("INFO_23 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
}
- if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_must_change_time);
- stored_time=pdb_get_pass_must_change_time(to);
- DEBUG(10,("INFO_23 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
- }
-
/* Backend should check this for sanity */
if ((from->fields_present & ACCT_USERNAME) &&
(from->hdr_user_name.buffer)) {
@@ -445,14 +404,13 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
pdb_set_workstations(to , new_string, PDB_CHANGED);
}
- /* is this right? */
- if ((from->fields_present & ACCT_ADMIN_DESC) &&
- (from->hdr_unknown_str.buffer)) {
- old_string = pdb_get_unknown_str(to);
- new_string = unistr2_static(&from->uni_unknown_str);
+ if ((from->fields_present & ACCT_COMMENT) &&
+ (from->hdr_comment.buffer)) {
+ old_string = pdb_get_comment(to);
+ new_string = unistr2_static(&from->uni_comment);
DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
if (STRING_CHANGED)
- pdb_set_unknown_str(to , new_string, PDB_CHANGED);
+ pdb_set_comment(to , new_string, PDB_CHANGED);
}
if ((from->fields_present & ACCT_CALLBACK) &&
@@ -461,6 +419,7 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
old_string = pdb_get_munged_dial(to);
mung.length = from->hdr_munged_dial.uni_str_len;
mung.data = (uint8 *) from->uni_munged_dial.buffer;
+ mung.free = NULL;
newstr = (mung.length == 0) ?
NULL : base64_encode_data_blob(mung);
DEBUG(10,("INFO_23 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
@@ -524,26 +483,16 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
}
}
- DEBUG(10,("INFO_23 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
- if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) {
- pdb_set_pass_must_change_time(to,0, PDB_CHANGED);
- } else {
- uint32 expire;
- time_t new_time;
- if (pdb_get_pass_must_change_time(to) == 0) {
- if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
- || expire == (uint32)-1) {
- new_time = get_time_t_max();
- } else {
- time_t old_time = pdb_get_pass_last_set_time(to);
- new_time = old_time + expire;
- if ((new_time) < time(0)) {
- new_time = time(0) + expire;
- }
- }
- if (!pdb_set_pass_must_change_time (to, new_time, PDB_CHANGED)) {
- DEBUG (0, ("pdb_set_pass_must_change_time failed!\n"));
- }
+ /* If the must change flag is set, the last set time goes to zero.
+ the must change and can change fields also do, but they are
+ calculated from policy, not set from the wire */
+
+ if (from->fields_present & ACCT_EXPIRED_FLAG) {
+ DEBUG(10,("INFO_23 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
+ if (from->passmustchange == PASS_MUST_CHANGE_AT_NEXT_LOGON) {
+ pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
+ } else {
+ pdb_set_pass_last_set_time(to, time(NULL),PDB_CHANGED);
}
}
@@ -564,7 +513,7 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
return;
if (from->fields_present & ACCT_LAST_LOGON) {
- unix_time=nt_time_to_unix(&from->logon_time);
+ unix_time=nt_time_to_unix(from->logon_time);
stored_time = pdb_get_logon_time(to);
DEBUG(10,("INFO_25 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -572,7 +521,7 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
}
if (from->fields_present & ACCT_LAST_LOGOFF) {
- unix_time=nt_time_to_unix(&from->logoff_time);
+ unix_time=nt_time_to_unix(from->logoff_time);
stored_time = pdb_get_logoff_time(to);
DEBUG(10,("INFO_25 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
@@ -580,37 +529,21 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
}
if (from->fields_present & ACCT_EXPIRY) {
- unix_time=nt_time_to_unix(&from->kickoff_time);
+ unix_time=nt_time_to_unix(from->kickoff_time);
stored_time = pdb_get_kickoff_time(to);
DEBUG(10,("INFO_25 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
}
- if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_can_change_time);
- stored_time = pdb_get_pass_can_change_time(to);
- DEBUG(10,("INFO_25 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
- }
-
if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_last_set_time);
+ unix_time=nt_time_to_unix(from->pass_last_set_time);
stored_time = pdb_get_pass_last_set_time(to);
DEBUG(10,("INFO_25 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
if (stored_time != unix_time)
pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
}
- if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
- unix_time=nt_time_to_unix(&from->pass_must_change_time);
- stored_time=pdb_get_pass_must_change_time(to);
- DEBUG(10,("INFO_25 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
- if (stored_time != unix_time)
- pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
- }
-
if ((from->fields_present & ACCT_USERNAME) &&
(from->hdr_user_name.buffer)) {
old_string = pdb_get_username(to);
@@ -683,14 +616,13 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
pdb_set_workstations(to , new_string, PDB_CHANGED);
}
- /* is this right? */
- if ((from->fields_present & ACCT_ADMIN_DESC) &&
- (from->hdr_unknown_str.buffer)) {
- old_string = pdb_get_unknown_str(to);
- new_string = unistr2_static(&from->uni_unknown_str);
+ if ((from->fields_present & ACCT_COMMENT) &&
+ (from->hdr_comment.buffer)) {
+ old_string = pdb_get_comment(to);
+ new_string = unistr2_static(&from->uni_comment);
DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
if (STRING_CHANGED)
- pdb_set_unknown_str(to , new_string, PDB_CHANGED);
+ pdb_set_comment(to , new_string, PDB_CHANGED);
}
if ((from->fields_present & ACCT_CALLBACK) &&
@@ -699,6 +631,7 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
old_string = pdb_get_munged_dial(to);
mung.length = from->hdr_munged_dial.uni_str_len;
mung.data = (uint8 *) from->uni_munged_dial.buffer;
+ mung.free = NULL;
newstr = (mung.length == 0) ?
NULL : base64_encode_data_blob(mung);
DEBUG(10,("INFO_25 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
diff --git a/source/rpc_server/srv_spoolss.c b/source/rpc_server/srv_spoolss.c
index 0a43e8ae8ac..c9ff9697e0a 100755
--- a/source/rpc_server/srv_spoolss.c
+++ b/source/rpc_server/srv_spoolss.c
@@ -910,6 +910,15 @@ static BOOL api_spoolss_addprinterdriver(pipes_struct *p)
ZERO_STRUCT(r_u);
if(!spoolss_io_q_addprinterdriver("", &q_u, data, 0)) {
+ if (q_u.level != 3 && q_u.level != 6) {
+ /* Clever hack from Martin Zielinski <mz@seh.de>
+ * to allow downgrade from level 8 (Vista).
+ */
+ DEBUG(3,("api_spoolss_addprinterdriver: unknown SPOOL_Q_ADDPRINTERDRIVER level %u.\n",
+ (unsigned int)q_u.level ));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_INVALID_TAG));
+ return True;
+ }
DEBUG(0,("spoolss_io_q_addprinterdriver: unable to unmarshall SPOOL_Q_ADDPRINTERDRIVER.\n"));
return False;
}
@@ -1477,6 +1486,15 @@ static BOOL api_spoolss_addprinterdriverex(pipes_struct *p)
ZERO_STRUCT(r_u);
if(!spoolss_io_q_addprinterdriverex("", &q_u, data, 0)) {
+ if (q_u.level != 3 && q_u.level != 6) {
+ /* Clever hack from Martin Zielinski <mz@seh.de>
+ * to allow downgrade from level 8 (Vista).
+ */
+ DEBUG(3,("api_spoolss_addprinterdriverex: unknown SPOOL_Q_ADDPRINTERDRIVEREX level %u.\n",
+ (unsigned int)q_u.level ));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_INVALID_TAG));
+ return True;
+ }
DEBUG(0,("spoolss_io_q_addprinterdriverex: unable to unmarshall SPOOL_Q_ADDPRINTERDRIVEREX.\n"));
return False;
}
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index ffe7f39ebe1..33bfaa6cc84 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -66,10 +66,6 @@ static uint32 smb_connections=0;
extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
-#define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
-((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
-
-
/* API table for Xcv Monitor functions */
struct xcv_api_table {
@@ -719,7 +715,8 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
}
data->notify_data.data.length = prs_offset(&ps);
- data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
+ data->notify_data.data.string = (uint16 *)
+ TALLOC(mem_ctx, prs_offset(&ps));
if (!data->notify_data.data.string) {
prs_mem_free(&ps);
return;
@@ -911,7 +908,8 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
/* need to allocate own copy of data */
if ( msg->len != 0 )
- msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
+ msg_grp->msgs[new_slot].notify.data = (char *)
+ TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
return ctr->num_groups;
}
@@ -1101,7 +1099,8 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, voi
********************************************************************/
static void receive_notify2_message_list(int msg_type, struct process_id src,
- void *msg, size_t len)
+ void *msg, size_t len,
+ void *private_data)
{
size_t msg_count, i;
char *buf = (char *)msg;
@@ -1213,14 +1212,15 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
over all printers, upgrading ones as necessary
**********************************************************************/
-void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
+void do_drv_upgrade_printer(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
fstring drivername;
int snum;
int n_services = lp_numservices();
len = MIN(len,sizeof(drivername)-1);
- strncpy(drivername, buf, len);
+ strncpy(drivername, (const char *)buf, len);
DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
@@ -1311,14 +1311,14 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername)
**********************************************************************/
void reset_all_printerdata(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
fstring drivername;
int snum;
int n_services = lp_numservices();
len = MIN( len, sizeof(drivername)-1 );
- strncpy( drivername, buf, len );
+ strncpy( drivername, (const char *)buf, len );
DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
@@ -1381,7 +1381,7 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
/* bulk copy first */
- d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
+ d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
if (!d)
return NULL;
@@ -1408,7 +1408,8 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
return NULL;
}
- d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
+ d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
+ devmode->driverextra);
if (!d->dev_private) {
return NULL;
}
@@ -2599,7 +2600,8 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
return False;
- message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
+ message_register(MSG_PRINTER_NOTIFY2,
+ receive_notify2_message_list, NULL);
/* Tell the connections db we're now interested in printer
* notify messages. */
register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
@@ -4080,7 +4082,7 @@ static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode
Create a DEVMODE struct. Returns malloced memory.
****************************************************************************/
-DEVICEMODE *construct_dev_mode(int snum)
+DEVICEMODE *construct_dev_mode(const char *servicename)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
DEVICEMODE *devmode = NULL;
@@ -4089,7 +4091,7 @@ DEVICEMODE *construct_dev_mode(int snum)
DEBUGADD(8,("getting printer characteristics\n"));
- if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
+ if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
return NULL;
if ( !printer->info_2->devmode ) {
@@ -4161,7 +4163,8 @@ static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *p
printer->cjobs = count; /* jobs */
printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
- if ( !(printer->devmode = construct_dev_mode(snum)) )
+ if ( !(printer->devmode = construct_dev_mode(
+ lp_const_servicename(snum))) )
DEBUG(8, ("Returning NULL Devicemode!\n"));
printer->secdesc = NULL;
@@ -4275,7 +4278,7 @@ static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *p
static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
{
char *guid_str = NULL;
- struct uuid guid;
+ struct GUID guid;
if (is_printer_published(print_hnd, snum, &guid)) {
asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
@@ -5296,8 +5299,7 @@ static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_IN
info->previousdrivernames=NULL;
init_unistr_array(&info->previousdrivernames, &nullstr, servername);
- info->driver_date.low=0;
- info->driver_date.high=0;
+ info->driver_date=0;
info->padding=0;
info->driver_version_low=0;
@@ -5848,6 +5850,12 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
goto done;
}
+ if (!secdesc_ctr) {
+ DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
/* Check the user has permissions to change the security
descriptor. By experimentation with two NT machines, the user
requires Full Access to the printer to change security
@@ -5875,10 +5883,10 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
for (i = 0; i < the_acl->num_aces; i++) {
fstring sid_str;
- sid_to_string(sid_str, &the_acl->ace[i].trustee);
+ sid_to_string(sid_str, &the_acl->aces[i].trustee);
DEBUG(10, ("%s 0x%08x\n", sid_str,
- the_acl->ace[i].info.mask));
+ the_acl->aces[i].access_mask));
}
the_acl = secdesc_ctr->sec->dacl;
@@ -5890,10 +5898,10 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
for (i = 0; i < the_acl->num_aces; i++) {
fstring sid_str;
- sid_to_string(sid_str, &the_acl->ace[i].trustee);
+ sid_to_string(sid_str, &the_acl->aces[i].trustee);
DEBUG(10, ("%s 0x%08x\n", sid_str,
- the_acl->ace[i].info.mask));
+ the_acl->aces[i].access_mask));
}
} else {
DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
@@ -6030,7 +6038,9 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
SE_PRIV se_printop = SE_PRINT_OPERATOR;
BOOL is_print_op = False;
- standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
+ standard_sub_basic(current_user_info.smb_name,
+ current_user_info.domain,
+ remote_machine,sizeof(remote_machine));
slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
cmd, printer->info_2->printername, printer->info_2->sharename,
@@ -6553,7 +6563,7 @@ static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
/* this should not be a failure condition if the devmode is NULL */
- devmode = construct_dev_mode(snum);
+ devmode = construct_dev_mode(lp_const_servicename(snum));
for (i=0; i<*returned; i++)
fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
@@ -8491,7 +8501,7 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
PRINTPROCDATATYPE_1 *info_1=NULL;
- WERROR result = WERR_NOMEM;
+ WERROR result = WERR_OK;
if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
return WERR_NOMEM;
@@ -8785,7 +8795,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
*/
if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
- devmode = construct_dev_mode(snum);
+ devmode = construct_dev_mode(lp_const_servicename(snum));
else {
if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
ZERO_STRUCTP( devmode );
@@ -9378,6 +9388,15 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
/* housekeeping information in the reply */
+ /* Fix from Martin Zielinski <mz@seh.de> - ensure
+ * the hand marshalled container size is a multiple
+ * of 4 bytes for RPC alignment.
+ */
+
+ if (needed % 4) {
+ needed += 4-(needed % 4);
+ }
+
r_u->needed = needed;
r_u->returned = num_entries;
@@ -9389,6 +9408,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
/* copy data into the reply */
r_u->ctr.size = r_u->needed;
+
r_u->ctr.size_of_array = r_u->returned;
r_u->ctr.values = enum_values;
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 9cce7159674..06a8c77098d 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -44,7 +44,7 @@ static uint32 get_share_type(int snum)
type = STYPE_PRINTQ;
if (strequal(lp_fstype(snum), "IPC"))
type = STYPE_IPC;
- if (net_name[len_net_name] == '$')
+ if (net_name[len_net_name-1] == '$')
type |= STYPE_HIDDEN;
return type;
@@ -128,52 +128,15 @@ static void map_generic_share_sd_bits(SEC_DESC *psd)
return;
for (i = 0; i < ps_dacl->num_aces; i++) {
- SEC_ACE *psa = &ps_dacl->ace[i];
- uint32 orig_mask = psa->info.mask;
+ SEC_ACE *psa = &ps_dacl->aces[i];
+ uint32 orig_mask = psa->access_mask;
- se_map_generic(&psa->info.mask, &file_generic_mapping);
- psa->info.mask |= orig_mask;
+ se_map_generic(&psa->access_mask, &file_generic_mapping);
+ psa->access_mask |= orig_mask;
}
}
/*******************************************************************
- Can this user access with share with the required permissions ?
-********************************************************************/
-
-BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, uint32 desired_access)
-{
- uint32 granted;
- NTSTATUS status;
- TALLOC_CTX *mem_ctx = NULL;
- SEC_DESC *psd = NULL;
- size_t sd_size;
- NT_USER_TOKEN *token = NULL;
- BOOL ret = True;
-
- mem_ctx = talloc_init("share_access_check");
- if (mem_ctx == NULL)
- return False;
-
- psd = get_share_security(mem_ctx, snum, &sd_size);
-
- if (!psd)
- goto out;
-
- if (conn->nt_user_token)
- token = conn->nt_user_token;
- else
- token = vuser->nt_user_token;
-
- ret = se_access_check(psd, token, desired_access, &granted, &status);
-
-out:
-
- talloc_destroy(mem_ctx);
-
- return ret;
-}
-
-/*******************************************************************
Fill in a share info level 501 structure.
********************************************************************/
@@ -221,7 +184,7 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
pstrcpy(passwd, "");
- sd = get_share_security(ctx, snum, &sd_size);
+ sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
init_srv_share_info502(&sh502->info_502, net_name, get_share_type(snum), remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
init_srv_share_info502_str(&sh502->info_502_str, net_name, remark, path, passwd, sd, sd_size);
@@ -294,7 +257,7 @@ static void init_srv_share_info_1501(pipes_struct *p, SRV_SHARE_INFO_1501 *sh150
ZERO_STRUCTP(sh1501);
- sd = get_share_security(ctx, snum, &sd_size);
+ sd = get_share_security(ctx, lp_servicename(snum), &sd_size);
sh1501->sdb = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
}
@@ -1227,7 +1190,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
become_root();
}
- if (message_send_pid(pid_to_procid(session_list[snum].pid), MSG_SHUTDOWN, NULL, 0, False))
+ if (NT_STATUS_IS_OK(message_send_pid(pid_to_procid(session_list[snum].pid), MSG_SHUTDOWN, NULL, 0, False)))
r_u->status = WERR_OK;
if (not_root)
@@ -1506,10 +1469,10 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
SEC_DESC *old_sd;
size_t sd_size;
- old_sd = get_share_security(p->mem_ctx, snum, &sd_size);
+ old_sd = get_share_security(p->mem_ctx, lp_servicename(snum), &sd_size);
if (old_sd && !sec_desc_equal(old_sd, psd)) {
- if (!set_share_security(p->mem_ctx, share_name, psd))
+ if (!set_share_security(share_name, psd))
DEBUG(0,("_srv_net_share_set_info: Failed to change security info in share %s.\n",
share_name ));
}
@@ -1661,7 +1624,7 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
return WERR_ACCESS_DENIED;
if (psd) {
- if (!set_share_security(p->mem_ctx, share_name, psd)) {
+ if (!set_share_security(share_name, psd)) {
DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n", share_name ));
}
}
@@ -1691,6 +1654,7 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
int snum;
SE_PRIV se_diskop = SE_DISK_OPERATOR;
BOOL is_disk_op;
+ struct share_params *params;
DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
@@ -1703,11 +1667,12 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
return WERR_ACCESS_DENIED;
}
+ if (!(params = get_share_params(p->mem_ctx, share_name))) {
+ return WERR_NO_SUCH_SHARE;
+ }
+
snum = find_service(share_name);
- if (snum < 0)
- return WERR_NO_SUCH_SHARE;
-
/* No change to printer shares. */
if (lp_print_ok(snum))
return WERR_ACCESS_DENIED;
@@ -1750,9 +1715,9 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
return WERR_ACCESS_DENIED;
/* Delete the SD in the database. */
- delete_share_security(snum);
+ delete_share_security(params);
- lp_killservice(snum);
+ lp_killservice(params->service);
return WERR_OK;
}
@@ -1826,7 +1791,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
pstring qualname;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
struct current_user user;
connection_struct *conn = NULL;
@@ -1861,33 +1825,35 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
became_user = True;
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
- unix_convert(filename, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(conn, filename, False, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
}
- if (!check_name(filename,conn)) {
+ nt_status = check_name(conn, filename);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
}
- fsp = open_file_stat(conn, filename, &st);
- if (!fsp) {
+ nt_status = open_file_stat(conn, filename, &st, &fsp);
+ if ( !NT_STATUS_IS_OK(nt_status)) {
/* Perhaps it is a directory */
if (errno == EISDIR)
- fsp = open_directory(conn, filename, &st,
+ nt_status = open_directory(conn, filename, &st,
READ_CONTROL_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
- NULL);
+ FILE_ATTRIBUTE_DIRECTORY,
+ NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
- r_u->status = WERR_ACCESS_DENIED;
+ r_u->status = ntstatus_to_werror(nt_status);
goto error_exit;
}
}
@@ -1941,7 +1907,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
DATA_BLOB null_pw;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- BOOL bad_path;
NTSTATUS nt_status;
struct current_user user;
connection_struct *conn = NULL;
@@ -1976,35 +1941,37 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
became_user = True;
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
- unix_convert(filename, conn, NULL, &bad_path, &st);
- if (bad_path) {
+ nt_status = unix_convert(conn, filename, False, NULL, &st);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
}
- if (!check_name(filename,conn)) {
+ nt_status = check_name(conn, filename);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", filename));
r_u->status = WERR_ACCESS_DENIED;
goto error_exit;
}
- fsp = open_file_stat(conn, filename, &st);
+ nt_status = open_file_stat(conn, filename, &st, &fsp);
- if (!fsp) {
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
/* Perhaps it is a directory */
if (errno == EISDIR)
- fsp = open_directory(conn, filename, &st,
+ nt_status = open_directory(conn, filename, &st,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
- NULL);
+ FILE_ATTRIBUTE_DIRECTORY,
+ NULL, &fsp);
- if (!fsp) {
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
- r_u->status = WERR_ACCESS_DENIED;
+ r_u->status = ntstatus_to_werror(nt_status);
goto error_exit;
}
}
diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c
index 6062dcee5ce..e202ec68b3f 100644
--- a/source/rpc_server/srv_svcctl_nt.c
+++ b/source/rpc_server/srv_svcctl_nt.c
@@ -302,7 +302,7 @@ WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_
return WERR_BADFID;
/* perform access checks. Use the root token in order to ensure that we
- retreive the security descriptor */
+ retrieve the security descriptor */
if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )
return WERR_NOMEM;
diff --git a/source/rpc_server/srv_wkssvc.c b/source/rpc_server/srv_wkssvc.c
deleted file mode 100644
index b5c1af34d9d..00000000000
--- a/source/rpc_server/srv_wkssvc.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997,
- * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* This is the interface to the wks pipe. */
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_RPC_SRV
-
-/*******************************************************************
- api_wks_query_info
- ********************************************************************/
-
-static BOOL api_wks_query_info(pipes_struct *p)
-{
- WKS_Q_QUERY_INFO q_u;
- WKS_R_QUERY_INFO r_u;
- prs_struct *data = &p->in_data.data;
- prs_struct *rdata = &p->out_data.rdata;
-
- ZERO_STRUCT(q_u);
- ZERO_STRUCT(r_u);
-
- /* grab the net share enum */
- if(!wks_io_q_query_info("", &q_u, data, 0))
- return False;
-
- r_u.status = _wks_query_info(p, &q_u, &r_u);
-
- /* store the response in the SMB stream */
- if(!wks_io_r_query_info("", &r_u, rdata, 0))
- return False;
-
- return True;
-}
-
-
-/*******************************************************************
- \PIPE\wkssvc commands
- ********************************************************************/
-
-static struct api_struct api_wks_cmds[] =
-{
- { "WKS_Q_QUERY_INFO", WKS_QUERY_INFO, api_wks_query_info }
-};
-
-void wkssvc_get_pipe_fns( struct api_struct **fns, int *n_fns )
-{
- *fns = api_wks_cmds;
- *n_fns = sizeof(api_wks_cmds) / sizeof(struct api_struct);
-}
-
-NTSTATUS rpc_wks_init(void)
-{
- return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "wkssvc", "ntsvcs", api_wks_cmds,
- sizeof(api_wks_cmds) / sizeof(struct api_struct));
-}
diff --git a/source/rpc_server/srv_wkssvc_nt.c b/source/rpc_server/srv_wkssvc_nt.c
index 6528e632251..1a827b265b6 100644
--- a/source/rpc_server/srv_wkssvc_nt.c
+++ b/source/rpc_server/srv_wkssvc_nt.c
@@ -1,10 +1,9 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Jeremy Allison 2001.
+ *
+ * Copyright (C) Andrew Tridgell 1992-1997,
+ * Copyright (C) Gerald (Jerry) Carter 2006.
*
* 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,51 +28,352 @@
#define DBGC_CLASS DBGC_RPC_SRV
/*******************************************************************
- create_wks_info_100
+ Fill in the valiues for the struct wkssvc_NetWkstaInfo100.
********************************************************************/
-static void create_wks_info_100(WKS_INFO_100 *inf)
+static void create_wks_info_100(struct wkssvc_NetWkstaInfo100 *info100)
{
pstring my_name;
pstring domain;
- DEBUG(5,("create_wks_info_100: %d\n", __LINE__));
-
pstrcpy (my_name, global_myname());
strupper_m(my_name);
pstrcpy (domain, lp_workgroup());
strupper_m(domain);
+
+ info100->platform_id = 0x000001f4; /* unknown */
+ info100->version_major = lp_major_announce_version();
+ info100->version_minor = lp_minor_announce_version();
+
+ info100->server_name = talloc_strdup( info100, my_name );
+ info100->domain_name = talloc_strdup( info100, domain );
- init_wks_info_100(inf,
- 0x000001f4, /* platform id info */
- lp_major_announce_version(),
- lp_minor_announce_version(),
- my_name, domain);
+ return;
}
-/*******************************************************************
- wks_reply_query_info
-
+/********************************************************************
only supports info level 100 at the moment.
+ ********************************************************************/
+
+WERROR _wkssvc_NetWkstaGetInfo( pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
+{
+ struct wkssvc_NetWkstaInfo100 *wks100 = NULL;
+
+ /* We only support info level 100 currently */
+
+ if ( r->in.level != 100 ) {
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ if ( (wks100 = TALLOC_ZERO_P(p->mem_ctx, struct wkssvc_NetWkstaInfo100)) == NULL ) {
+ return WERR_NOMEM;
+ }
+
+ create_wks_info_100( wks100 );
+
+ r->out.info->info100 = wks100;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetWkstaSetInfo( pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetWkstaEnumUsers( pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRWKSTAUSERGETINFO( pipes_struct *p, struct WKSSVC_NETRWKSTAUSERGETINFO *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRWKSTAUSERSETINFO( pipes_struct *p, struct WKSSVC_NETRWKSTAUSERSETINFO *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetWkstaTransportEnum( pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRWKSTATRANSPORTADD( pipes_struct *p, struct WKSSVC_NETRWKSTATRANSPORTADD *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRWKSTATRANSPORTDEL( pipes_struct *p, struct WKSSVC_NETRWKSTATRANSPORTDEL *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRUSEADD( pipes_struct *p, struct WKSSVC_NETRUSEADD *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRUSEGETINFO( pipes_struct *p, struct WKSSVC_NETRUSEGETINFO *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRUSEDEL( pipes_struct *p, struct WKSSVC_NETRUSEDEL *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRUSEENUM( pipes_struct *p, struct WKSSVC_NETRUSEENUM *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRMESSAGEBUFFERSEND( pipes_struct *p, struct WKSSVC_NETRMESSAGEBUFFERSEND *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRWORKSTATIONSTATISTICSGET( pipes_struct *p, struct WKSSVC_NETRWORKSTATIONSTATISTICSGET *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+/********************************************************************
********************************************************************/
-NTSTATUS _wks_query_info(pipes_struct *p, WKS_Q_QUERY_INFO *q_u, WKS_R_QUERY_INFO *r_u)
+WERROR _WKSSVC_NETRLOGONDOMAINNAMEADD( pipes_struct *p, struct WKSSVC_NETRLOGONDOMAINNAMEADD *r )
{
- WKS_INFO_100 *wks100 = NULL;
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRLOGONDOMAINNAMEDEL( pipes_struct *p, struct WKSSVC_NETRLOGONDOMAINNAMEDEL *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRJOINDOMAIN( pipes_struct *p, struct WKSSVC_NETRJOINDOMAIN *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRUNJOINDOMAIN( pipes_struct *p, struct WKSSVC_NETRUNJOINDOMAIN *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRRENAMEMACHINEINDOMAIN( pipes_struct *p, struct WKSSVC_NETRRENAMEMACHINEINDOMAIN *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
- DEBUG(5,("_wks_query_info: %d\n", __LINE__));
+/********************************************************************
+ ********************************************************************/
- wks100 = TALLOC_ZERO_P(p->mem_ctx, WKS_INFO_100);
+WERROR _WKSSVC_NETRVALIDATENAME( pipes_struct *p, struct WKSSVC_NETRVALIDATENAME *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
- if (!wks100)
- return NT_STATUS_NO_MEMORY;
+/********************************************************************
+ ********************************************************************/
- create_wks_info_100(wks100);
- init_wks_r_query_info(r_u, q_u->switch_value, wks100, NT_STATUS_OK);
+WERROR _WKSSVC_NETRGETJOININFORMATION( pipes_struct *p, struct WKSSVC_NETRGETJOININFORMATION *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
- DEBUG(5,("_wks_query_info: %d\n", __LINE__));
+/********************************************************************
+ ********************************************************************/
- return r_u->status;
+WERROR _WKSSVC_NETRGETJOINABLEOUS( pipes_struct *p, struct WKSSVC_NETRGETJOINABLEOUS *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, struct wkssvc_NetrJoinDomain2 *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p, struct wkssvc_NetrUnjoinDomain2 *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRVALIDATENAME2( pipes_struct *p, struct WKSSVC_NETRVALIDATENAME2 *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRGETJOINABLEOUS2( pipes_struct *p, struct WKSSVC_NETRGETJOINABLEOUS2 *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRSETPRIMARYCOMPUTERNAME( pipes_struct *p, struct WKSSVC_NETRSETPRIMARYCOMPUTERNAME *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+WERROR _WKSSVC_NETRENUMERATECOMPUTERNAMES( pipes_struct *p, struct WKSSVC_NETRENUMERATECOMPUTERNAMES *r )
+{
+ /* FIXME: Add implementation code here */
+ p->rng_fault_state = True;
+ return WERR_NOT_SUPPORTED;
+}
+
diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c
index 97a707c020a..a130def4f57 100644
--- a/source/rpcclient/cmd_lsarpc.c
+++ b/source/rpcclient/cmd_lsarpc.c
@@ -31,7 +31,7 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *cli,
DOM_SID *sid, const char *name)
{
POLICY_HND pol;
- uint32 *sid_types;
+ enum lsa_SidType *sid_types;
NTSTATUS result;
DOM_SID *sids;
@@ -63,9 +63,9 @@ static void display_query_info_1(DOM_QUERY_1 d)
{
d_printf("percent_full:\t%d\n", d.percent_full);
d_printf("log_size:\t%d\n", d.log_size);
- d_printf("retention_time:\t%08x %08x\n", d.retention_time.high, d.retention_time.low);
+ d_printf("retention_time:\t%lld\n", (long long)d.retention_time);
d_printf("shutdown_in_progress:\t%d\n", d.shutdown_in_progress);
- d_printf("time_to_shutdown:\t%08x %08x\n", d.time_to_shutdown.high, d.time_to_shutdown.low);
+ d_printf("time_to_shutdown:\t%lld\n", (long long)d.time_to_shutdown);
d_printf("next_audit_record:\t%d\n", d.next_audit_record);
d_printf("unknown:\t%d\n", d.unknown);
}
@@ -223,7 +223,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli,
POLICY_HND pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
DOM_SID *sids;
- uint32 *types;
+ enum lsa_SidType *types;
int i;
if (argc == 1) {
@@ -272,7 +272,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem
DOM_SID *sids;
char **domains;
char **names;
- uint32 *types;
+ enum lsa_SidType *types;
int i;
if (argc == 1) {
diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c
index 4608c6b3da3..f199a4a0f2c 100644
--- a/source/rpcclient/cmd_netlogon.c
+++ b/source/rpcclient/cmd_netlogon.c
@@ -263,7 +263,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
uint32 database_id, num_deltas, tmp;
SAM_DELTA_HDR *hdr_deltas;
SAM_DELTA_CTR *deltas;
- UINT64_S seqnum;
+ uint64 seqnum;
if (argc != 3) {
fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]);
@@ -273,8 +273,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
database_id = atoi(argv[1]);
tmp = atoi(argv[2]);
- seqnum.low = tmp & 0xffff;
- seqnum.high = 0;
+ seqnum = tmp & 0xffff;
result = rpccli_netlogon_sam_deltas(cli, mem_ctx, database_id,
seqnum, &num_deltas,
@@ -302,11 +301,12 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli,
const char *username, *password;
int auth_level = 2;
uint32 logon_param = 0;
+ const char *workstation = NULL;
/* Check arguments */
- if (argc < 3 || argc > 6) {
- fprintf(stderr, "Usage: samlogon <username> <password> "
+ if (argc < 3 || argc > 7) {
+ fprintf(stderr, "Usage: samlogon <username> <password> [workstation]"
"[logon_type (1 or 2)] [auth level (2 or 3)] [logon_parameter]\n");
return NT_STATUS_OK;
}
@@ -314,18 +314,21 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli,
username = argv[1];
password = argv[2];
- if (argc >= 4)
- sscanf(argv[3], "%i", &logon_type);
+ if (argc >= 4)
+ workstation = argv[3];
if (argc >= 5)
- sscanf(argv[4], "%i", &auth_level);
+ sscanf(argv[4], "%i", &logon_type);
- if (argc == 6)
- sscanf(argv[5], "%x", &logon_param);
+ if (argc >= 6)
+ sscanf(argv[5], "%i", &auth_level);
+
+ if (argc == 7)
+ sscanf(argv[6], "%x", &logon_param);
/* Perform the sam logon */
- result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, logon_type);
+ result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, logon_type);
if (!NT_STATUS_IS_OK(result))
goto done;
diff --git a/source/rpcclient/cmd_reg.c b/source/rpcclient/cmd_reg.c
deleted file mode 100644
index e8038d094e6..00000000000
--- a/source/rpcclient/cmd_reg.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NT Domain Authentication SMB / MSRPC client
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997
- Copyright (C) Simo Sorce 2001
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "rpcclient.h"
-
-/*
- * keys. of the form:
- * ----
- *
- * [HKLM]|[HKU]\[parent_keyname_components]\[subkey]|[value]
- *
- * reg_getsubkey() splits this down into:
- * [HKLM]|[HKU]\[parent_keyname_components] and [subkey]|[value]
- *
- * do_reg_connect() splits the left side down further into:
- * [HKLM]|[HKU] and [parent_keyname_components].
- *
- * HKLM is short for HKEY_LOCAL_MACHINE
- * HKU is short for HKEY_USERS
- *
- * oh, and HKEY stands for "Hive Key".
- *
- */
-
-#if 0 /* This whole file need to be rewritten for the current rpcclient interface */
-
-/****************************************************************************
-nt registry enum
-****************************************************************************/
-static void cmd_reg_enum(struct client_info *info)
-{
- BOOL res = True;
- BOOL res1 = True;
- BOOL res2 = True;
- int i;
-
- POLICY_HND key_pol;
- fstring full_keyname;
- fstring key_name;
- uint32 reg_type;
-
- /*
- * query key info
- */
-
- fstring key_class;
- uint32 max_class_len = 0;
- uint32 num_subkeys;
- uint32 max_subkeylen;
- uint32 max_subkeysize;
- uint32 num_values;
- uint32 max_valnamelen;
- uint32 max_valbufsize;
- uint32 sec_desc;
- NTTIME mod_time;
-
- /*
- * unknown 0x1a request
- */
-
- uint32 unk_1a_response;
-
- DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "regenum <key_name>\n");
- return;
- }
-
- if (!reg_split_key(full_keyname, &reg_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;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*key_name) != 0)
- {
- /* open an entry */
- res1 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
- }
- else
- {
- memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
- }
-
- res1 = res1 ? do_reg_query_key(smb_cli,
- &key_pol,
- key_class, &max_class_len,
- &num_subkeys, &max_subkeylen, &max_subkeysize,
- &num_values, &max_valnamelen, &max_valbufsize,
- &sec_desc, &mod_time) : False;
-
- if (res1 && num_subkeys > 0)
- {
- fprintf(out_hnd,"Subkeys\n");
- fprintf(out_hnd,"-------\n");
- }
-
- for (i = 0; i < num_subkeys; i++)
- {
- /*
- * enumerate key
- */
-
- fstring enum_name;
- uint32 enum_unk1;
- uint32 enum_unk2;
- time_t key_mod_time;
-
- /* unknown 1a it */
- res2 = res1 ? do_reg_getversion(smb_cli, &key_pol,
- &unk_1a_response) : False;
-
- if (res2 && unk_1a_response != 5)
- {
- fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
- }
-
- /* enum key */
- res2 = res2 ? do_reg_enum_key(smb_cli, &key_pol,
- i, enum_name,
- &enum_unk1, &enum_unk2,
- &key_mod_time) : False;
-
- if (res2)
- {
- display_reg_key_info(out_hnd, ACTION_HEADER , enum_name, key_mod_time);
- display_reg_key_info(out_hnd, ACTION_ENUMERATE, enum_name, key_mod_time);
- display_reg_key_info(out_hnd, ACTION_FOOTER , enum_name, key_mod_time);
- }
-
- }
-
- if (num_values > 0)
- {
- fprintf(out_hnd,"Key Values\n");
- fprintf(out_hnd,"----------\n");
- }
-
- for (i = 0; i < num_values; i++)
- {
- /*
- * enumerate key
- */
-
- uint32 val_type;
- REGVAL_BUFFER value;
- fstring val_name;
-
- /* unknown 1a it */
- res2 = res1 ? do_reg_getversion(smb_cli, &key_pol,
- &unk_1a_response) : False;
-
- if (res2 && unk_1a_response != 5)
- {
- fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
- }
-
- /* enum key */
- res2 = res2 ? do_reg_enum_val(smb_cli, &key_pol,
- i, max_valnamelen, max_valbufsize,
- val_name, &val_type, &value) : False;
-
- if (res2)
- {
- display_reg_value_info(out_hnd, ACTION_HEADER , val_name, val_type, &value);
- display_reg_value_info(out_hnd, ACTION_ENUMERATE, val_name, val_type, &value);
- display_reg_value_info(out_hnd, ACTION_FOOTER , val_name, val_type, &value);
- }
- }
-
- /* close the handles */
- if ((*key_name) != 0)
- {
- res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
- }
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res1 && res2)
- {
- DEBUG(5,("cmd_reg_enum: query succeeded\n"));
- }
- else
- {
- DEBUG(5,("cmd_reg_enum: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry query key
-****************************************************************************/
-static void cmd_reg_query_key(struct client_info *info)
-{
- BOOL res = True;
- BOOL res1 = True;
-
- POLICY_HND key_pol;
- fstring full_keyname;
- fstring key_name;
-
- /*
- * query key info
- */
-
- fstring key_class;
- uint32 key_class_len = 0;
- uint32 num_subkeys;
- uint32 max_subkeylen;
- uint32 max_subkeysize;
- uint32 num_values;
- uint32 max_valnamelen;
- uint32 max_valbufsize;
- uint32 sec_desc;
- NTTIME mod_time;
-
- DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "regquery key_name\n");
- return;
- }
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*key_name) != 0)
- {
- /* open an entry */
- res1 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
- }
- else
- {
- memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
- }
-
- res1 = res1 ? do_reg_query_key(smb_cli,
- &key_pol,
- key_class, &key_class_len,
- &num_subkeys, &max_subkeylen, &max_subkeysize,
- &num_values, &max_valnamelen, &max_valbufsize,
- &sec_desc, &mod_time) : False;
-
- if (res1 && key_class_len != 0)
- {
- res1 = res1 ? do_reg_query_key(smb_cli,
- &key_pol,
- key_class, &key_class_len,
- &num_subkeys, &max_subkeylen, &max_subkeysize,
- &num_values, &max_valnamelen, &max_valbufsize,
- &sec_desc, &mod_time) : False;
- }
-
- if (res1)
- {
- fprintf(out_hnd,"Registry Query Info Key\n");
- fprintf(out_hnd,"key class: %s\n", key_class);
- fprintf(out_hnd,"subkeys, max_len, max_size: %d %d %d\n", num_subkeys, max_subkeylen, max_subkeysize);
- fprintf(out_hnd,"vals, max_len, max_size: 0x%x 0x%x 0x%x\n", num_values, max_valnamelen, max_valbufsize);
- fprintf(out_hnd,"sec desc: 0x%x\n", sec_desc);
- fprintf(out_hnd,"mod time: %s\n", http_timestring(nt_time_to_unix(&mod_time)));
- }
-
- /* close the handles */
- if ((*key_name) != 0)
- {
- res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
- }
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res1)
- {
- DEBUG(5,("cmd_reg_query: query succeeded\n"));
- }
- else
- {
- DEBUG(5,("cmd_reg_query: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry create value
-****************************************************************************/
-static void cmd_reg_set_val(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND parent_pol;
- fstring full_keyname;
- fstring keyname;
- fstring parent_name;
- fstring val_name;
- fstring tmp;
- uint32 val_type;
- RPC_DATA_BLOB value;
-
-#if 0
- uint32 unk_0;
- uint32 unk_1;
- /* query it */
- res1 = res1 ? do_reg_query_info(smb_cli, &val_pol,
- val_name, *val_type) : False;
-#endif
-
- 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)))
- {
- fprintf(out_hnd, "regcreate <val_name> <val_type> <val>\n");
- return;
- }
-
- reg_get_subkey(full_keyname, keyname, val_name);
-
- if (keyname[0] == 0 || val_name[0] == 0)
- {
- fprintf(out_hnd, "invalid key name\n");
- return;
- }
-
- if (!next_token_nr(NULL, tmp, NULL, sizeof(tmp)))
- {
- fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
- return;
- }
-
- val_type = atoi(tmp);
-
- if (val_type != 1 && val_type != 3 && val_type != 4)
- {
- fprintf(out_hnd, "val_type 1=UNISTR, 3=BYTES, 4=DWORD supported\n");
- return;
- }
-
- if (!next_token_nr(NULL, tmp, NULL, sizeof(tmp)))
- {
- fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
- return;
- }
-
- switch (val_type)
- {
- case 0x01: /* UNISTR */
- {
- init_rpc_blob_str(&value, tmp, strlen(tmp)+1);
- break;
- }
- case 0x03: /* BYTES */
- {
- init_rpc_blob_hex(&value, tmp);
- break;
- }
- case 0x04: /* DWORD */
- {
- uint32 tmp_val;
- if (strnequal(tmp, "0x", 2))
- {
- tmp_val = strtol(tmp, (char**)NULL, 16);
- }
- else
- {
- tmp_val = strtol(tmp, (char**)NULL, 10);
- }
- init_rpc_blob_uint32(&value, tmp_val);
- break;
- }
- default:
- {
- fprintf(out_hnd, "i told you i only deal with UNISTR, DWORD and BYTES!\n");
- return;
- }
- }
-
- DEBUG(10,("key data:\n"));
- dump_data(10, (char *)value.buffer, value.buf_len);
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, keyname, parent_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*val_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- parent_name, 0x02000000, &parent_pol) : False;
- }
- else
- {
- memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
- }
-
- /* create an entry */
- res4 = res3 ? do_reg_set_val(smb_cli, &parent_pol,
- val_name, val_type, &value) : False;
-
- /* flush the modified key */
- res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
-
- /* close the val handle */
- if ((*val_name) != 0)
- {
- res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
- }
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_set_val: query succeeded\n"));
- fprintf(out_hnd,"OK\n");
- }
- else
- {
- DEBUG(5,("cmd_reg_set_val: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry delete value
-****************************************************************************/
-static void cmd_reg_delete_val(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND parent_pol;
- fstring full_keyname;
- fstring keyname;
- fstring parent_name;
- fstring val_name;
-
- DEBUG(5, ("cmd_reg_delete_val: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "regdelete <val_name>\n");
- return;
- }
-
- reg_get_subkey(full_keyname, keyname, val_name);
-
- if (keyname[0] == 0 || val_name[0] == 0)
- {
- fprintf(out_hnd, "invalid key name\n");
- return;
- }
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, keyname, parent_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*val_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- parent_name, 0x02000000, &parent_pol) : False;
- }
- else
- {
- memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
- }
-
- /* delete an entry */
- res4 = res3 ? do_reg_delete_val(smb_cli, &parent_pol, val_name) : False;
-
- /* flush the modified key */
- res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
-
- /* close the key handle */
- res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_delete_val: query succeeded\n"));
- fprintf(out_hnd,"OK\n");
- }
- else
- {
- DEBUG(5,("cmd_reg_delete_val: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry delete key
-****************************************************************************/
-static void cmd_reg_delete_key(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND parent_pol;
- fstring full_keyname;
- fstring parent_name;
- fstring key_name;
- fstring subkey_name;
-
- DEBUG(5, ("cmd_reg_delete_key: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "regdeletekey <key_name>\n");
- return;
- }
-
- reg_get_subkey(full_keyname, parent_name, subkey_name);
-
- if (parent_name[0] == 0 || subkey_name[0] == 0)
- {
- fprintf(out_hnd, "invalid key name\n");
- return;
- }
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, parent_name, key_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*key_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &parent_pol) : False;
- }
- else
- {
- memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
- }
-
- /* create an entry */
- res4 = res3 ? do_reg_delete_key(smb_cli, &parent_pol, subkey_name) : False;
-
- /* flush the modified key */
- res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
-
- /* close the key handle */
- if ((*key_name) != 0)
- {
- res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
- }
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_delete_key: query succeeded\n"));
- fprintf(out_hnd,"OK\n");
- }
- else
- {
- DEBUG(5,("cmd_reg_delete_key: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry create key
-****************************************************************************/
-static void cmd_reg_create_key(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND parent_pol;
- POLICY_HND key_pol;
- fstring full_keyname;
- fstring parent_key;
- fstring parent_name;
- fstring key_name;
- fstring key_class;
- SEC_ACCESS sam_access;
-
- DEBUG(5, ("cmd_reg_create_key: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "regcreate <key_name> [key_class]\n");
- return;
- }
-
- reg_get_subkey(full_keyname, parent_key, key_name);
-
- if (parent_key[0] == 0 || key_name[0] == 0)
- {
- fprintf(out_hnd, "invalid key name\n");
- return;
- }
-
- if (!next_token_nr(NULL, key_class, NULL, sizeof(key_class)))
- {
- memset(key_class, 0, sizeof(key_class));
- }
-
- /* set access permissions */
- sam_access.mask = SEC_RIGHTS_READ;
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, parent_key, parent_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*parent_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- parent_name, 0x02000000, &parent_pol) : False;
- }
- else
- {
- memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
- }
-
- /* create an entry */
- res4 = res3 ? do_reg_create_key(smb_cli, &parent_pol,
- key_name, key_class, &sam_access, &key_pol) : False;
-
- /* flush the modified key */
- res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
-
- /* close the key handle */
- res4 = res4 ? do_reg_close(smb_cli, &key_pol) : False;
-
- /* close the key handle */
- if ((*parent_name) != 0)
- {
- res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
- }
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_create_key: query succeeded\n"));
- fprintf(out_hnd,"OK\n");
- }
- else
- {
- DEBUG(5,("cmd_reg_create_key: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry security info
-****************************************************************************/
-static void cmd_reg_test_key_sec(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND key_pol;
- fstring full_keyname;
- fstring key_name;
-
- /*
- * security info
- */
-
- uint32 sec_buf_size;
- SEC_DESC_BUF *psdb;
-
- DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "reggetsec <key_name>\n");
- return;
- }
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*key_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
- }
- else
- {
- memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
- }
-
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
-
- /* query key sec info. first call sets sec_buf_size. */
-
- sec_buf_size = 0;
- res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
- &sec_buf_size, &psdb) : False;
-
- free_sec_desc_buf(&psdb);
-
- res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
- &sec_buf_size, &psdb) : False;
-
- if (res4 && psdb->len > 0 && psdb->sec != NULL)
- {
- display_sec_desc(out_hnd, ACTION_HEADER , psdb->sec);
- display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
- display_sec_desc(out_hnd, ACTION_FOOTER , psdb->sec);
-
- res4 = res4 ? do_reg_set_key_sec(smb_cli, &key_pol, psdb) : False;
- }
-
- free_sec_desc_buf(&psdb);
-
- /* close the key handle */
- if ((*key_name) != 0)
- {
- res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
- }
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_test2: query succeeded\n"));
- fprintf(out_hnd,"Registry Test2\n");
- }
- else
- {
- DEBUG(5,("cmd_reg_test2: query failed\n"));
- }
-}
-
-/****************************************************************************
-nt registry security info
-****************************************************************************/
-static void cmd_reg_get_key_sec(struct client_info *info)
-{
- BOOL res = True;
- BOOL res3 = True;
- BOOL res4 = True;
-
- POLICY_HND key_pol;
- fstring full_keyname;
- fstring key_name;
-
- /*
- * security info
- */
-
- uint32 sec_buf_size;
- SEC_DESC_BUF *psdb;
-
- DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
-
- if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
- {
- fprintf(out_hnd, "reggetsec <key_name>\n");
- return;
- }
-
- /* open WINREG session. */
- res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
-
- /* open registry receive a policy handle */
- res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
- &info->dom.reg_pol_connect) : False;
-
- if ((*key_name) != 0)
- {
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
- }
- else
- {
- memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
- }
-
- /* open an entry */
- res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
- key_name, 0x02000000, &key_pol) : False;
-
- /* Get the size. */
- sec_buf_size = 0;
- res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
- &sec_buf_size, &psdb) : False;
-
- free_sec_desc_buf(&psdb);
-
- res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
- &sec_buf_size, &psdb) : False;
-
- if (res4 && psdb->len > 0 && psdb->sec != NULL)
- {
- display_sec_desc(out_hnd, ACTION_HEADER , psdb->sec);
- display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
- display_sec_desc(out_hnd, ACTION_FOOTER , psdb->sec);
- }
-
- free_sec_desc_buf(&psdb);
-
- /* close the key handle */
- if ((*key_name) != 0)
- {
- res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
- }
-
- /* close the registry handles */
- res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
- /* close the session */
- cli_nt_session_close(smb_cli);
-
- if (res && res3 && res4)
- {
- DEBUG(5,("cmd_reg_get_key_sec: query succeeded\n"));
- }
- else
- {
- DEBUG(5,("cmd_reg_get_key_sec: query failed\n"));
- }
-}
-
-
-/****************************************************************************
-nt registry shutdown
-****************************************************************************/
-static NTSTATUS cmd_reg_shutdown(struct cli_state *cli, TALLOC_CTX *mem_ctx,
- int argc, const char **argv)
-{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- fstring msg;
- uint32 timeout = 20;
- BOOL force = False;
- BOOL reboot = False;
- int opt;
-
- *msg = 0;
- optind = 0; /* TODO: test if this hack works on other systems too --simo */
-
- while ((opt = getopt(argc, argv, "m:t:rf")) != EOF)
- {
- /*fprintf (stderr, "[%s]\n", argv[argc-1]);*/
-
- switch (opt)
- {
- case 'm':
- fstrcpy(msg, optarg);
- /*fprintf (stderr, "[%s|%s]\n", optarg, msg);*/
- break;
-
- case 't':
- timeout = atoi(optarg);
- /*fprintf (stderr, "[%s|%d]\n", optarg, timeout);*/
- break;
-
- case 'r':
- reboot = True;
- break;
-
- case 'f':
- force = True;
- break;
-
- }
- }
-
- /* create an entry */
- result = werror_to_ntstatus(cli_reg_shutdown(cli, mem_ctx, msg, timeout, reboot, force));
-
- if (NT_STATUS_IS_OK(result))
- DEBUG(5,("cmd_reg_shutdown: query succeeded\n"));
- else
- DEBUG(5,("cmd_reg_shutdown: query failed\n"));
-
- return result;
-}
-
-/****************************************************************************
-abort a shutdown
-****************************************************************************/
-static NTSTATUS cmd_reg_abort_shutdown(struct cli_state *cli,
- TALLOC_CTX *mem_ctx, int argc,
- const char **argv)
-{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
- result = werror_to_ntstatus(cli_reg_abort_shutdown(cli, mem_ctx));
-
- if (NT_STATUS_IS_OK(result))
- DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
- else
- DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
-
- return result;
-}
-
-#endif /* This whole file need to be rewritten for the cirrent rpcclient interface */
-
-
-/* List of commands exported by this module */
-struct cmd_set reg_commands[] = {
-
- { "REG" },
-#if 0
- { "shutdown", RPC_RTYPE_NTSTATUS, cmd_reg_shutdown, NULL, PI_WINREG, "Remote Shutdown",
- "syntax: shutdown [-m message] [-t timeout] [-r] [-h] [-f] (-r == reboot, -h == halt, -f == force)" },
-
- { "abortshutdown", RPC_RTYPE_NTSTATUS, cmd_reg_abort_shutdown, NULL, PI_WINREG, "Abort Shutdown",
- "syntax: abortshutdown" },
- { "regenum", cmd_reg_enum, "Registry Enumeration", "<keyname>" },
- { "regdeletekey", cmd_reg_delete_key, "Registry Key Delete", "<keyname>" },
- { "regcreatekey", cmd_reg_create_key, "Registry Key Create", "<keyname> [keyclass]" },
- { "regqueryval", cmd_reg_query_info, "Registry Value Query", "<valname>" },
- { "regquerykey", cmd_reg_query_key, "Registry Key Query", "<keyname>" },
- { "regdeleteval", cmd_reg_delete_val, "Registry Value Delete", "<valname>" },
- { "regsetval", cmd_reg_set_val, "Registry Key Create", "<valname> <valtype> <value>" },
- { "reggetsec", cmd_reg_get_key_sec, "Registry Key Security", "<keyname>" },
- { "regtestsec", cmd_reg_test_key_sec, "Test Registry Key Security", "<keyname>" },
-#endif
- { NULL }
-};
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index 86ba20bb45c..e2a026c87bf 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -47,6 +47,14 @@ static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
}
/****************************************************************************
+ display sam_user_info_16 structure
+ ****************************************************************************/
+static void display_sam_user_info_16(SAM_USER_INFO_16 *usr)
+{
+ printf("\tAcct Flags :\tox%x\n", usr->acb_info);
+}
+
+/****************************************************************************
display sam_user_info_21 structure
****************************************************************************/
static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
@@ -77,24 +85,24 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
printf("\tWorkstations:\t%s\n", temp);
- unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
+ unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp)-1);
printf("\tUnknown Str :\t%s\n", temp);
unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
printf("\tRemote Dial :\t%s\n", temp);
printf("\tLogon Time :\t%s\n",
- http_timestring(nt_time_to_unix(&usr->logon_time)));
+ http_timestring(nt_time_to_unix(usr->logon_time)));
printf("\tLogoff Time :\t%s\n",
- http_timestring(nt_time_to_unix(&usr->logoff_time)));
+ http_timestring(nt_time_to_unix(usr->logoff_time)));
printf("\tKickoff Time :\t%s\n",
- http_timestring(nt_time_to_unix(&usr->kickoff_time)));
+ http_timestring(nt_time_to_unix(usr->kickoff_time)));
printf("\tPassword last set Time :\t%s\n",
- http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
+ http_timestring(nt_time_to_unix(usr->pass_last_set_time)));
printf("\tPassword can change Time :\t%s\n",
- http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
+ http_timestring(nt_time_to_unix(usr->pass_can_change_time)));
printf("\tPassword must change Time:\t%s\n",
- http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
+ http_timestring(nt_time_to_unix(usr->pass_must_change_time)));
printf("\tunknown_2[0..31]...\n"); /* user passwords? */
@@ -114,40 +122,6 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
}
}
-static const char *display_time(NTTIME nttime)
-{
- static fstring string;
-
- float high;
- float low;
- int sec;
- int days, hours, mins, secs;
-
- if (nttime.high==0 && nttime.low==0)
- return "Now";
-
- if (nttime.high==0x80000000 && nttime.low==0)
- return "Never";
-
- high = 65536;
- high = high/10000;
- high = high*65536;
- high = high/1000;
- high = high * (~nttime.high);
-
- low = ~nttime.low;
- low = low/(1000*1000*10);
-
- sec=high+low;
-
- days=sec/(60*60*24);
- hours=(sec - (days*60*60*24)) / (60*60);
- mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
- secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
-
- fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
- return (string);
-}
static void display_password_properties(uint32 password_properties)
{
@@ -199,7 +173,7 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
printf("Total Groups:\t%d\n", info2->num_domain_grps);
printf("Total Aliases:\t%d\n", info2->num_local_grps);
- printf("Sequence No:\t%d\n", info2->seq_num.low);
+ printf("Sequence No:\t%llu\n", (unsigned long long)info2->seq_num);
printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
@@ -244,9 +218,9 @@ static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
{
- printf("Sequence No:\t%d\n", info8->seq_num.low);
+ printf("Sequence No:\t%llu\n", (unsigned long long)info8->seq_num);
printf("Domain Create Time:\t%s\n",
- http_timestring(nt_time_to_unix(&info8->domain_create_time)));
+ http_timestring(nt_time_to_unix(info8->domain_create_time)));
}
static void display_sam_unk_info_9(SAM_UNK_INFO_9 *info9)
@@ -263,9 +237,9 @@ static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
static void display_sam_unk_info_13(SAM_UNK_INFO_13 *info13)
{
- printf("Sequence No:\t%d\n", info13->seq_num.low);
+ printf("Sequence No:\t%llu\n", (unsigned long long)info13->seq_num);
printf("Domain Create Time:\t%s\n",
- http_timestring(nt_time_to_unix(&info13->domain_create_time)));
+ http_timestring(nt_time_to_unix(info13->domain_create_time)));
printf("Unknown1:\t%d\n", info13->unknown1);
printf("Unknown2:\t%d\n", info13->unknown2);
@@ -376,14 +350,14 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
SAM_USERINFO_CTR *user_ctr;
fstring server;
- uint32 user_rid;
+ uint32 user_rid = 0;
if ((argc < 2) || (argc > 4)) {
printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
return NT_STATUS_OK;
}
- user_rid = strtoul(argv[1], NULL, 10);
+ sscanf(argv[1], "%i", &user_rid);
if (argc > 2)
sscanf(argv[2], "%i", &info_level);
@@ -445,15 +419,18 @@ static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
goto done;
switch (user_ctr->switch_value) {
- case 21:
- display_sam_user_info_21(user_ctr->info.id21);
- break;
case 7:
display_sam_user_info_7(user_ctr->info.id7);
break;
case 9:
display_sam_user_info_9(user_ctr->info.id9);
break;
+ case 16:
+ display_sam_user_info_16(user_ctr->info.id16);
+ break;
+ case 21:
+ display_sam_user_info_21(user_ctr->info.id21);
+ break;
default:
printf("Unsupported infolevel: %d\n", info_level);
break;
@@ -718,7 +695,9 @@ static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli,
printf("%s is not a legal SID\n", argv[i]);
return NT_STATUS_INVALID_PARAMETER;
}
- add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
+ if (!add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids)) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
@@ -821,7 +800,7 @@ static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
goto done;
/* Make sure to wait for our DC's reply */
- old_timeout = cli_set_timeout(cli->cli, 30000); /* 30 seconds. */
+ old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
&num_members, &group_rids,
@@ -2072,6 +2051,60 @@ done:
/* Change user password */
+static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *user, *oldpass, *newpass;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if (argc < 3) {
+ printf("Usage: %s username oldpass newpass\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ user = argv[1];
+ oldpass = argv[2];
+ newpass = argv[3];
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Change user password */
+ result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+
+/* Change user password */
+
static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
int argc, const char **argv)
@@ -2178,6 +2211,7 @@ struct cmd_set samr_commands[] = {
{ "getusrdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo, NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
{ "lookupdomain", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain, NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
+ { "chgpasswd2", RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2, NULL, PI_SAMR, NULL, "Change user password", "" },
{ "chgpasswd3", RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3, NULL, PI_SAMR, NULL, "Change user password", "" },
{ NULL }
};
diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c
index ed5653eb704..6e6d7986f5a 100644
--- a/source/rpcclient/cmd_spoolss.c
+++ b/source/rpcclient/cmd_spoolss.c
@@ -2012,7 +2012,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
if (!W_ERROR_IS_OK(result))
goto done;
- printf("%s\n", timestring(True));
+ printf("%s\n", current_timestring(True));
printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
/* Set the printer data */
@@ -2024,13 +2024,15 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
UNISTR2 data;
init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
value.size = data.uni_str_len * 2;
- value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
+ value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
+ value.size);
break;
}
case REG_DWORD: {
uint32 data = strtoul(argv[4], NULL, 10);
value.size = sizeof(data);
- value.data_p = TALLOC_MEMDUP(mem_ctx, &data, sizeof(data));
+ value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
+ sizeof(data));
break;
}
case REG_BINARY: {
@@ -2088,7 +2090,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
if (!W_ERROR_IS_OK(result))
goto done;
- printf("%s\n", timestring(True));
+ printf("%s\n", current_timestring(True));
printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
done:
diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c
index d5425aa43d1..e40bda08c2d 100644
--- a/source/rpcclient/rpcclient.c
+++ b/source/rpcclient/rpcclient.c
@@ -463,7 +463,6 @@ extern struct cmd_set spoolss_commands[];
extern struct cmd_set netlogon_commands[];
extern struct cmd_set srvsvc_commands[];
extern struct cmd_set dfs_commands[];
-extern struct cmd_set reg_commands[];
extern struct cmd_set ds_commands[];
extern struct cmd_set echo_commands[];
extern struct cmd_set shutdown_commands[];
@@ -478,7 +477,6 @@ static struct cmd_set *rpcclient_command_list[] = {
netlogon_commands,
srvsvc_commands,
dfs_commands,
- reg_commands,
echo_commands,
shutdown_commands,
test_commands,
diff --git a/source/sam/idmap.c b/source/sam/idmap.c
deleted file mode 100644
index aa5b923d3dd..00000000000
--- a/source/sam/idmap.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- ID Mapping
- Copyright (C) Tim Potter 2000
- Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
- Copyright (C) Simo Sorce 2003
- Copyright (C) Jeremy Allison 2003.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-static_decl_idmap;
-
-struct idmap_function_entry {
- const char *name;
- struct idmap_methods *methods;
- struct idmap_function_entry *prev,*next;
-};
-
-static struct idmap_function_entry *backends = NULL;
-
-static struct idmap_methods *cache_map;
-static struct idmap_methods *remote_map;
-
-static BOOL proxyonly = False;
-
-/**********************************************************************
- Get idmap methods. Don't allow tdb to be a remote method.
-**********************************************************************/
-
-static struct idmap_methods *get_methods(const char *name, BOOL cache_method)
-{
- struct idmap_function_entry *entry = backends;
-
- for(entry = backends; entry; entry = entry->next) {
- if (!cache_method && strequal(entry->name, "tdb"))
- continue; /* tdb is only cache method. */
- if (strequal(entry->name, name))
- return entry->methods;
- }
-
- return NULL;
-}
-
-/**********************************************************************
- Allow a module to register itself as a method.
-**********************************************************************/
-
-NTSTATUS smb_register_idmap(int version, const char *name, struct idmap_methods *methods)
-{
- struct idmap_function_entry *entry;
-
- if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
- DEBUG(0, ("smb_register_idmap: Failed to register idmap module.\n"
- "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n"
- "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
- "Please recompile against the current version of samba!\n",
- version, SMB_IDMAP_INTERFACE_VERSION));
- return NT_STATUS_OBJECT_TYPE_MISMATCH;
- }
-
- if (!name || !name[0] || !methods) {
- DEBUG(0,("smb_register_idmap: called with NULL pointer or empty name!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (get_methods(name, False)) {
- DEBUG(0,("smb_register_idmap: idmap module %s already registered!\n", name));
- return NT_STATUS_OBJECT_NAME_COLLISION;
- }
-
- entry = SMB_XMALLOC_P(struct idmap_function_entry);
- entry->name = smb_xstrdup(name);
- entry->methods = methods;
-
- DLIST_ADD(backends, entry);
- DEBUG(5, ("smb_register_idmap: Successfully added idmap backend '%s'\n", name));
- return NT_STATUS_OK;
-}
-
-/**********************************************************************
- Initialise idmap cache and a remote backend (if configured).
-**********************************************************************/
-
-BOOL idmap_init(const char **remote_backend)
-{
- if (!backends)
- static_init_idmap;
-
- if (!cache_map) {
- cache_map = get_methods("tdb", True);
-
- if (!cache_map) {
- DEBUG(0, ("idmap_init: could not find tdb cache backend!\n"));
- return False;
- }
-
- if (!NT_STATUS_IS_OK(cache_map->init( NULL ))) {
- DEBUG(0, ("idmap_init: could not initialise tdb cache backend!\n"));
- return False;
- }
- }
-
- if ((remote_map == NULL) && (remote_backend != NULL) &&
- (*remote_backend != NULL) && (**remote_backend != '\0')) {
- char *rem_backend = smb_xstrdup(*remote_backend);
- fstring params = "";
- char *pparams;
- BOOL idmap_prefix_workaround = False;
-
- /* get any mode parameters passed in */
-
- if ( (pparams = strchr( rem_backend, ':' )) != NULL ) {
- *pparams = '\0';
- pparams++;
- fstrcpy( params, pparams );
- }
-
- /* strip any leading idmap_ prefix of */
- if ( strncmp( rem_backend, "idmap_", 6) == 0 ) {
- rem_backend += 6;
- idmap_prefix_workaround = True;
- DEBUG(0, ("idmap_init: idmap backend uses deprecated 'idmap_' prefix. Please replace 'idmap_%s' by '%s' in %s\n", rem_backend, rem_backend, dyn_CONFIGFILE));
- }
-
- DEBUG(3, ("idmap_init: using '%s' as remote backend\n", rem_backend));
-
- if((remote_map = get_methods(rem_backend, False)) ||
- (NT_STATUS_IS_OK(smb_probe_module("idmap", rem_backend)) &&
- (remote_map = get_methods(rem_backend, False)))) {
- if (!NT_STATUS_IS_OK(remote_map->init(params))) {
- DEBUG(0, ("idmap_init: failed to initialize remote backend!\n"));
- return False;
- }
- } else {
- DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", rem_backend));
- if (idmap_prefix_workaround)
- rem_backend -= 6;
- SAFE_FREE(rem_backend);
- return False;
- }
- if (idmap_prefix_workaround)
- rem_backend -= 6;
- SAFE_FREE(rem_backend);
- }
-
- return True;
-}
-
-/**************************************************************************
- Don't do id mapping. This is used to make winbind a netlogon proxy only.
-**************************************************************************/
-
-void idmap_set_proxyonly(void)
-{
- proxyonly = True;
-}
-
-BOOL idmap_proxyonly(void)
-{
- return proxyonly;
-}
-
-/**************************************************************************
- This is a rare operation, designed to allow an explicit mapping to be
- set up for a sid to a POSIX id.
-**************************************************************************/
-
-NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- struct idmap_methods *map = remote_map;
- DOM_SID tmp_sid;
-
- if (proxyonly)
- return NT_STATUS_UNSUCCESSFUL;
-
- if (sid_check_is_in_our_domain(sid)) {
- DEBUG(3, ("Refusing to add SID %s to idmap, it's our own "
- "domain\n", sid_string_static(sid)));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (sid_check_is_in_builtin(sid)) {
- DEBUG(3, ("Refusing to add SID %s to idmap, it's our builtin "
- "domain\n", sid_string_static(sid)));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
- sid_string_static(sid),
- ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID",
- ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid :
- (unsigned long)id.gid));
-
- if ( (NT_STATUS_IS_OK(cache_map->
- get_sid_from_id(&tmp_sid, id,
- id_type | ID_QUERY_ONLY))) &&
- sid_equal(sid, &tmp_sid) ) {
- /* Nothing to do, we already have that mapping */
- DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
- return NT_STATUS_OK;
- }
-
- if (map == NULL) {
- /* Ok, we don't have a authoritative remote
- mapping. So update our local cache only. */
- map = cache_map;
- }
-
- return map->set_mapping(sid, id, id_type);
-}
-
-/**************************************************************************
- Get ID from SID. This can create a mapping for a SID to a POSIX id.
-**************************************************************************/
-
-NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
-{
- NTSTATUS ret;
- int loc_type;
- unid_t loc_id;
-
- if (proxyonly)
- return NT_STATUS_UNSUCCESSFUL;
-
- if (sid_check_is_in_our_domain(sid)) {
- DEBUG(9, ("sid %s is in our domain -- go look in passdb\n",
- sid_string_static(sid)));
- return NT_STATUS_NONE_MAPPED;
- }
-
- if (sid_check_is_in_builtin(sid)) {
- DEBUG(9, ("sid %s is in builtin domain -- go look in passdb\n",
- sid_string_static(sid)));
- return NT_STATUS_NONE_MAPPED;
- }
-
- loc_type = *id_type;
-
- if (remote_map) {
- /* We have a central remote idmap so only look in
- cache, don't allocate */
- loc_type |= ID_QUERY_ONLY;
- }
-
- ret = cache_map->get_id_from_sid(id, &loc_type, sid);
-
- if (NT_STATUS_IS_OK(ret)) {
- *id_type = loc_type & ID_TYPEMASK;
- return NT_STATUS_OK;
- }
-
- if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY)) {
- return ret;
- }
-
- /* Before forking out to the possibly slow remote map, lets see if we
- * already have the sid as uid when asking for a gid or vice versa. */
-
- loc_type = *id_type & ID_TYPEMASK;
-
- switch (loc_type) {
- case ID_USERID:
- loc_type = ID_GROUPID;
- break;
- case ID_GROUPID:
- loc_type = ID_USERID;
- break;
- default:
- loc_type = ID_EMPTY;
- }
-
- loc_type |= ID_QUERY_ONLY;
-
- ret = cache_map->get_id_from_sid(&loc_id, &loc_type, sid);
-
- if (NT_STATUS_IS_OK(ret)) {
- /* Ok, we have the uid as gid or vice versa. The remote map
- * would not know anything different, so return here. */
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* Ok, the mapping was not in the cache, give the remote map a
- second try. */
-
- ret = remote_map->get_id_from_sid(id, id_type, sid);
-
- if (NT_STATUS_IS_OK(ret)) {
- /* The remote backend gave us a valid mapping, cache it. */
- ret = cache_map->set_mapping(sid, *id, *id_type);
- }
-
- return ret;
-}
-
-/**************************************************************************
- Get SID from ID. This must have been created before.
-**************************************************************************/
-
-NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
-{
- NTSTATUS ret;
- int loc_type;
-
- if (proxyonly)
- return NT_STATUS_UNSUCCESSFUL;
-
- loc_type = id_type;
- if (remote_map) {
- loc_type = id_type | ID_QUERY_ONLY;
- }
-
- ret = cache_map->get_sid_from_id(sid, id, loc_type);
-
- if (NT_STATUS_IS_OK(ret))
- return ret;
-
- if ((remote_map == NULL) || (loc_type & ID_CACHE_ONLY))
- return ret;
-
- /* We have a second chance, ask our authoritative backend */
-
- ret = remote_map->get_sid_from_id(sid, id, id_type);
-
- if (NT_STATUS_IS_OK(ret)) {
- /* The remote backend gave us a valid mapping, cache it. */
- ret = cache_map->set_mapping(sid, id, id_type);
- }
-
- return ret;
-}
-
-/**************************************************************************
- Alloocate a new UNIX uid/gid
-**************************************************************************/
-
-NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
-{
- /* we have to allocate from the authoritative backend */
-
- if (proxyonly)
- return NT_STATUS_UNSUCCESSFUL;
-
- if ( remote_map )
- return remote_map->allocate_id( id, id_type );
-
- return cache_map->allocate_id( id, id_type );
-}
-
-/**************************************************************************
- Shutdown maps.
-**************************************************************************/
-
-NTSTATUS idmap_close(void)
-{
- NTSTATUS ret;
-
- if (proxyonly)
- return NT_STATUS_OK;
-
- ret = cache_map->close_fn();
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(3, ("idmap_close: failed to close local tdb cache!\n"));
- }
- cache_map = NULL;
-
- if (remote_map) {
- ret = remote_map->close_fn();
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n"));
- }
- remote_map = NULL;
- }
-
- return ret;
-}
-
-/**************************************************************************
- Dump backend status.
-**************************************************************************/
-
-void idmap_status(void)
-{
- cache_map->status();
- if (remote_map)
- remote_map->status();
-}
diff --git a/source/sam/idmap_ad.c b/source/sam/idmap_ad.c
deleted file mode 100644
index 5bf039fa1aa..00000000000
--- a/source/sam/idmap_ad.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts
- *
- * Unix SMB/CIFS implementation.
- *
- * Winbind ADS backend functions
- *
- * Copyright (C) Andrew Tridgell 2001
- * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
- * Copyright (C) Gerald (Jerry) Carter 2004
- * Copyright (C) Luke Howard 2001-2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
-
-NTSTATUS init_module(void);
-
-static ADS_STRUCT *ad_idmap_ads = NULL;
-
-static char *attr_uidnumber = NULL;
-static char *attr_gidnumber = NULL;
-
-static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
-{
- ADS_STATUS status;
- enum wb_posix_mapping map_type;
-
- if (attr_uidnumber != NULL && attr_gidnumber != NULL) {
- return ADS_ERROR(LDAP_SUCCESS);
- }
-
- SMB_ASSERT(ads->server.workgroup);
-
- map_type = get_nss_info(ads->server.workgroup);
-
- if ((map_type == WB_POSIX_MAP_SFU) ||
- (map_type == WB_POSIX_MAP_RFC2307)) {
-
- status = ads_check_posix_schema_mapping(ads, map_type);
- if (ADS_ERR_OK(status)) {
- attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr);
- attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr);
- ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
- ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
- return ADS_ERROR(LDAP_SUCCESS);
- } else {
- DEBUG(0,("ads_check_posix_schema_mapping failed: %s\n", ads_errstr(status)));
- /* return status; */
- }
- }
-
- /* fallback to XAD defaults */
- attr_uidnumber = SMB_STRDUP("uidNumber");
- attr_gidnumber = SMB_STRDUP("gidNumber");
- ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
- ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
-
- return ADS_ERROR(LDAP_SUCCESS);
-}
-
-static ADS_STRUCT *ad_idmap_cached_connection(void)
-{
- ADS_STRUCT *ads;
- ADS_STATUS status;
- BOOL local = False;
-
- if (ad_idmap_ads != NULL) {
- ads = ad_idmap_ads;
-
- /* check for a valid structure */
-
- DEBUG(7, ("Current tickets expire at %d, time is now %d\n",
- (uint32) ads->auth.expire, (uint32) time(NULL)));
- if ( ads->config.realm && (ads->auth.expire > time(NULL))) {
- return ads;
- } else {
- /* we own this ADS_STRUCT so make sure it goes away */
- ads->is_mine = True;
- ads_destroy( &ads );
- ads_kdestroy(WINBIND_CCACHE_NAME);
- ad_idmap_ads = NULL;
- }
- }
-
- if (!local) {
- /* we don't want this to affect the users ccache */
- setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
- }
-
- ads = ads_init(lp_realm(), lp_workgroup(), NULL);
- if (!ads) {
- DEBUG(1,("ads_init failed\n"));
- return NULL;
- }
-
- /* the machine acct password might have change - fetch it every time */
- SAFE_FREE(ads->auth.password);
- ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-
- SAFE_FREE(ads->auth.realm);
- ads->auth.realm = SMB_STRDUP(lp_realm());
-
- status = ads_connect(ads);
- if (!ADS_ERR_OK(status)) {
- DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
- ads_destroy(&ads);
- return NULL;
- }
-
- ads->is_mine = False;
-
- status = ad_idmap_check_attr_mapping(ads);
- if (!ADS_ERR_OK(status)) {
- DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n"));
- return NULL;
- }
-
- ad_idmap_ads = ads;
- return ads;
-}
-
-/* no op */
-static NTSTATUS ad_idmap_init(char *uri)
-{
- return NT_STATUS_OK;
-}
-
-static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
-{
- ADS_STATUS rc;
- NTSTATUS status = NT_STATUS_NONE_MAPPED;
- const char *attrs[] = { "objectSid", NULL };
- void *res = NULL;
- void *msg = NULL;
- char *expr = NULL;
- fstring sid_string;
- int count;
- ADS_STRUCT *ads;
-
- if (sid == NULL) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ads = ad_idmap_cached_connection();
- if (ads == NULL) {
- DEBUG(1, ("ad_idmap_get_id_from_sid ADS uninitialized\n"));
- return NT_STATUS_NOT_SUPPORTED;
- }
-
- switch (id_type & ID_TYPEMASK) {
- case ID_USERID:
- if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
- ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
- ads->schema.posix_uidnumber_attr, (int)unid.uid) == -1) {
- return NT_STATUS_NO_MEMORY;
- }
- break;
- case ID_GROUPID:
- if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
- ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
- ads->schema.posix_gidnumber_attr, (int)unid.gid) == -1) {
- return NT_STATUS_NO_MEMORY;
- }
- break;
- default:
- return NT_STATUS_INVALID_PARAMETER;
- break;
- }
-
- rc = ads_search_retry(ads, &res, expr, attrs);
- free(expr);
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1, ("ad_idmap_get_sid_from_id: ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- count = ads_count_replies(ads, res);
- if (count == 0) {
- DEBUG(1, ("ad_idmap_get_sid_from_id: ads_count_replies: no results\n"));
- goto done;
- } else if (count != 1) {
- DEBUG(1, ("ad_idmap_get_sid_from_id: ads_count_replies: incorrect cardinality\n"));
- goto done;
- }
-
- msg = ads_first_entry(ads, res);
- if (msg == NULL) {
- DEBUG(1, ("ad_idmap_get_sid_from_id: ads_first_entry: could not retrieve search result\n"));
- goto done;
- }
-
- if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
- DEBUG(1, ("ad_idmap_get_sid_from_id: ads_pull_sid: could not retrieve SID from entry\n"));
- goto done;
- }
-
- status = NT_STATUS_OK;
- DEBUG(1, ("ad_idmap_get_sid_from_id mapped POSIX %s %d to SID [%s]\n",
- (id_type == ID_GROUPID) ? "GID" : "UID", (int)unid.uid,
- sid_to_string(sid_string, sid)));
-
-done:
- if (res != NULL) {
- ads_msgfree(ads, res);
- }
-
- return status;
-}
-
-static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid)
-{
- ADS_STATUS rc;
- NTSTATUS status = NT_STATUS_NONE_MAPPED;
- const char *attrs[] = { "sAMAccountType", ADS_ATTR_SFU_UIDNUMBER_OID,
- ADS_ATTR_SFU_GIDNUMBER_OID,
- ADS_ATTR_RFC2307_UIDNUMBER_OID,
- ADS_ATTR_RFC2307_GIDNUMBER_OID,
- NULL };
- void *res = NULL;
- void *msg = NULL;
- char *expr = NULL;
- uint32 atype, uid;
- char *sidstr;
- fstring sid_string;
- int count;
- ADS_STRUCT *ads;
-
- if (unid == NULL) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ads = ad_idmap_cached_connection();
- if (ads == NULL) {
- DEBUG(1, ("ad_idmap_get_id_from_sid ADS uninitialized\n"));
- return NT_STATUS_NOT_SUPPORTED;
- }
-
- sidstr = sid_binstring(sid);
- if (asprintf(&expr, "(objectSid=%s)", sidstr) == -1) {
- free(sidstr);
- return NT_STATUS_NO_MEMORY;
- }
-
- rc = ads_search_retry(ads, &res, expr, attrs);
- free(sidstr);
- free(expr);
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- count = ads_count_replies(ads, res);
- if (count == 0) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_count_replies: no results\n"));
- goto done;
- } else if (count != 1) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_count_replies: incorrect cardinality\n"));
- goto done;
- }
-
- msg = ads_first_entry(ads, res);
- if (msg == NULL) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_first_entry: could not retrieve search result\n"));
- goto done;
- }
-
- if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_pull_uint32: could not read SAM account type\n"));
- goto done;
- }
-
- switch (atype & 0xF0000000) {
- case ATYPE_SECURITY_GLOBAL_GROUP:
- case ATYPE_SECURITY_LOCAL_GROUP:
- *id_type = ID_GROUPID;
- break;
- case ATYPE_NORMAL_ACCOUNT:
- case ATYPE_WORKSTATION_TRUST:
- case ATYPE_INTERDOMAIN_TRUST:
- *id_type = ID_USERID;
- break;
- default:
- DEBUG(1, ("ad_idmap_get_id_from_sid: unrecognized SAM account type %08x\n", atype));
- goto done;
- break;
- }
-
- if (!ads_pull_uint32(ads, msg, (*id_type == ID_GROUPID) ? attr_gidnumber : attr_uidnumber, &uid)) {
- DEBUG(1, ("ad_idmap_get_id_from_sid: ads_pull_uint32: could not read attribute '%s'\n",
- (*id_type == ID_GROUPID) ? attr_gidnumber : attr_uidnumber));
- goto done;
- }
-
- unid->uid = (uid_t)uid;
-
- status = NT_STATUS_OK;
- DEBUG(1, ("ad_idmap_get_id_from_sid mapped SID [%s] to POSIX %s %d\n",
- sid_to_string(sid_string, sid),
- (*id_type == ID_GROUPID) ? "GID" : "UID", uid));
-
-done:
- if (res != NULL) {
- ads_msgfree(ads, res);
- }
-
- return status;
-
-}
-
-static NTSTATUS ad_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- /* Not supported, and probably won't be... */
- /* (It's not particularly feasible with a single-master model.) */
-
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS ad_idmap_close(void)
-{
- ADS_STRUCT *ads = ad_idmap_ads;
-
- if (ads != NULL) {
- /* we own this ADS_STRUCT so make sure it goes away */
- ads->is_mine = True;
- ads_destroy( &ads );
- ad_idmap_ads = NULL;
- }
-
- SAFE_FREE(attr_uidnumber);
- SAFE_FREE(attr_gidnumber);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS ad_idmap_allocate_id(unid_t *id, int id_type)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static void ad_idmap_status(void)
-{
- DEBUG(0, ("AD IDMAP Status not available\n"));
-}
-
-static struct idmap_methods ad_methods = {
- ad_idmap_init,
- ad_idmap_allocate_id,
- ad_idmap_get_sid_from_id,
- ad_idmap_get_id_from_sid,
- ad_idmap_set_mapping,
- ad_idmap_close,
- ad_idmap_status
-};
-
-
-/* support for new authentication subsystem */
-NTSTATUS init_module(void)
-{
- return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods);
-}
-
diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c
deleted file mode 100644
index 6169c89b3b9..00000000000
--- a/source/sam/idmap_ldap.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- idmap LDAP backend
-
- Copyright (C) Tim Potter 2000
- Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
- Copyright (C) Simo Sorce 2003
- Copyright (C) Gerald Carter 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-
-#include <lber.h>
-#include <ldap.h>
-
-#include "smbldap.h"
-
-struct ldap_idmap_state {
- struct smbldap_state *smbldap_state;
- TALLOC_CTX *mem_ctx;
-};
-
-static struct ldap_idmap_state ldap_state;
-
-/* number tries while allocating new id */
-#define LDAP_MAX_ALLOC_ID 128
-
-
-/***********************************************************************
- This function cannot be called to modify a mapping, only set a new one
-***********************************************************************/
-
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- pstring dn;
- pstring id_str;
- fstring type;
- LDAPMod **mods = NULL;
- int rc = -1;
- int ldap_op;
- fstring sid_string;
- LDAPMessage *entry = NULL;
-
- sid_to_string( sid_string, sid );
-
- ldap_op = LDAP_MOD_ADD;
- pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID),
- sid_string, lp_ldap_idmap_suffix());
-
- if ( id_type & ID_USERID )
- fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) );
- else
- fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
-
- pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid :
- (unsigned long)id.gid));
-
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY );
-
- smbldap_make_mod( ldap_state.smbldap_state->ldap_struct,
- entry, &mods, type, id_str );
-
- smbldap_make_mod( ldap_state.smbldap_state->ldap_struct,
- entry, &mods,
- get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
- sid_string );
-
- /* There may well be nothing at all to do */
-
- if (mods) {
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY );
- rc = smbldap_add(ldap_state.smbldap_state, dn, mods);
- ldap_mods_free( mods, True );
- } else {
- rc = LDAP_SUCCESS;
- }
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n",
- (ldap_op == LDAP_MOD_ADD) ? "add" : "replace",
- sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type));
- DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
- ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
- sid_string, ((id_type & ID_USERID) ? (unsigned long)id.uid :
- (unsigned long)id.gid), type));
-
- return NT_STATUS_OK;
-}
-
-/*****************************************************************************
- Allocate a new uid or gid
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- int rc = LDAP_SERVER_DOWN;
- int count = 0;
- LDAPMessage *result = NULL;
- LDAPMessage *entry = NULL;
- pstring id_str, new_id_str;
- LDAPMod **mods = NULL;
- const char *type;
- char *dn = NULL;
- const char **attr_list;
- pstring filter;
- uid_t luid, huid;
- gid_t lgid, hgid;
-
-
- type = (id_type & ID_USERID) ?
- get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) :
- get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
-
- pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
-
- attr_list = get_attr_list( NULL, idpool_attr_list );
-
- rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
- LDAP_SCOPE_SUBTREE, filter,
- attr_list, 0, &result);
- TALLOC_FREE( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL));
- goto out;
- }
-
- count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
- if (count != 1) {
- DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL));
- goto out;
- }
-
- dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
- if (!dn) {
- goto out;
- }
- entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
-
- if (!smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) {
- DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
- type));
- goto out;
- }
-
- /* this must succeed or else we wouldn't have initialized */
-
- lp_idmap_uid( &luid, &huid);
- lp_idmap_gid( &lgid, &hgid);
-
- /* make sure we still have room to grow */
-
- if (id_type & ID_USERID) {
- id->uid = strtoul(id_str, NULL, 10);
- if (id->uid > huid ) {
- DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n",
- (unsigned long)huid));
- goto out;
- }
- }
- else {
- id->gid = strtoul(id_str, NULL, 10);
- if (id->gid > hgid ) {
- DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n",
- (unsigned long)hgid));
- goto out;
- }
- }
-
- pstr_sprintf(new_id_str, "%lu",
- ((id_type & ID_USERID) ? (unsigned long)id->uid :
- (unsigned long)id->gid) + 1);
-
- smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str );
-
- if (mods == NULL) {
- DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n"));
- goto out;
- }
-
- rc = smbldap_modify(ldap_state.smbldap_state, dn, mods);
-
- ldap_mods_free( mods, True );
- if (rc != LDAP_SUCCESS) {
- DEBUG(1,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n",
- type));
- goto out;
- }
-
- ret = NT_STATUS_OK;
-out:
- SAFE_FREE(dn);
- if (result != NULL)
- ldap_msgfree(result);
-
- return ret;
-}
-
-/*****************************************************************************
- get a sid from an id
-*****************************************************************************/
-
-static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
-{
- LDAPMessage *result = NULL;
- LDAPMessage *entry = NULL;
- pstring sid_str;
- pstring filter;
- pstring suffix;
- const char *type;
- int rc;
- int count;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- const char **attr_list;
-
- if ( id_type & ID_USERID )
- type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
- else
- type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
-
- pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
- LDAP_OBJ_IDMAP_ENTRY, type,
- ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
-
- attr_list = get_attr_list( NULL, sidmap_attr_list );
- rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
- filter, attr_list, 0, &result);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n",
- ldap_err2string(rc) ));
- goto out;
- }
-
- count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-
- if (count != 1) {
- DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n",
- type, ((id_type & ID_USERID) ? (unsigned long)id.uid :
- (unsigned long)id.gid)));
- goto out;
- }
-
- entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
-
- if ( !smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) )
- goto out;
-
- if (!string_to_sid(sid, sid_str))
- goto out;
-
- ret = NT_STATUS_OK;
-out:
- TALLOC_FREE( attr_list );
-
- if (result)
- ldap_msgfree(result);
-
- return ret;
-}
-
-/***********************************************************************
- Get an id from a sid
-***********************************************************************/
-
-static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
-{
- LDAPMessage *result = NULL;
- LDAPMessage *entry = NULL;
- pstring sid_str;
- pstring filter;
- pstring id_str;
- const char *suffix;
- const char *type;
- int rc;
- int count;
- const char **attr_list;
- char *dn = NULL;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- sid_to_string(sid_str, sid);
-
- DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str,
- (*id_type & ID_GROUPID ? "group" : "user") ));
-
- suffix = lp_ldap_idmap_suffix();
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
-
- if ( *id_type & ID_GROUPID )
- type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER );
- else
- type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
-
- /* do the search and check for errors */
-
- attr_list = get_attr_list( NULL, sidmap_attr_list );
- rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
- filter, attr_list, 0, &result);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n",
- ldap_err2string(rc) ));
- goto out;
- }
-
- /* check for the number of entries returned */
-
- count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-
- if ( count > 1 ) {
- DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n",
- filter, count));
- goto out;
- }
-
- /* try to allocate a new id if we still haven't found one */
-
- if ( !count ) {
- int i;
-
- if (*id_type & ID_QUERY_ONLY) {
- DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n"));
- goto out;
- }
-
- DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n"));
-
- for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
- ret = ldap_allocate_id(id, *id_type);
- if ( NT_STATUS_IS_OK(ret) )
- break;
- }
-
- if ( !NT_STATUS_IS_OK(ret) ) {
- DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n"));
- goto out;
- }
-
- DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
- (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid ));
-
- ret = ldap_set_mapping(sid, *id, *id_type);
-
- /* all done */
-
- goto out;
- }
-
- DEBUG(10,("ldap_get_id_from_sid: success\n"));
-
- entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
-
- dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
- if (!dn)
- goto out;
-
- DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
-
- if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) {
- if ( (*id_type & ID_USERID) )
- id->uid = strtoul(id_str, NULL, 10);
- else
- id->gid = strtoul(id_str, NULL, 10);
-
- ret = NT_STATUS_OK;
- goto out;
- }
-
-out:
- TALLOC_FREE( attr_list );
- if (result)
- ldap_msgfree(result);
- SAFE_FREE(dn);
-
- return ret;
-}
-
-/**********************************************************************
- Verify the sambaUnixIdPool entry in the directiry.
-**********************************************************************/
-
-static NTSTATUS verify_idpool( void )
-{
- fstring filter;
- int rc;
- const char **attr_list;
- LDAPMessage *result = NULL;
- LDAPMod **mods = NULL;
- int count;
-
- fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL );
-
- attr_list = get_attr_list( NULL, idpool_attr_list );
- rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result);
- TALLOC_FREE( attr_list );
-
- if (rc != LDAP_SUCCESS)
- return NT_STATUS_UNSUCCESSFUL;
-
- count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
-
- ldap_msgfree(result);
-
- if ( count > 1 ) {
- DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n",
- filter, lp_ldap_idmap_suffix() ));
- return NT_STATUS_UNSUCCESSFUL;
- }
- else if (count == 0) {
- uid_t luid, huid;
- gid_t lgid, hgid;
- fstring uid_str, gid_str;
-
- if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) {
- DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- fstr_sprintf( uid_str, "%lu", (unsigned long)luid );
- fstr_sprintf( gid_str, "%lu", (unsigned long)lgid );
-
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL );
- smbldap_set_mod( &mods, LDAP_MOD_ADD,
- get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str );
- smbldap_set_mod( &mods, LDAP_MOD_ADD,
- get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str );
- if (mods) {
- rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
- ldap_mods_free( mods, True );
- } else {
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
-
- return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-}
-
-/*****************************************************************************
- Initialise idmap database.
-*****************************************************************************/
-
-static NTSTATUS ldap_idmap_init( char *params )
-{
- NTSTATUS nt_status;
-
- ldap_state.mem_ctx = talloc_init("idmap_ldap");
- if (!ldap_state.mem_ctx) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* assume location is the only parameter */
- if (!NT_STATUS_IS_OK(nt_status =
- smbldap_init(ldap_state.mem_ctx, params,
- &ldap_state.smbldap_state))) {
- talloc_destroy(ldap_state.mem_ctx);
- return nt_status;
- }
-
- /* see if the idmap suffix and sub entries exists */
-
- nt_status = verify_idpool();
- if ( !NT_STATUS_IS_OK(nt_status) )
- return nt_status;
-
- return NT_STATUS_OK;
-}
-
-/*****************************************************************************
- End the LDAP session
-*****************************************************************************/
-
-static NTSTATUS ldap_idmap_close(void)
-{
-
- smbldap_free_struct(&(ldap_state).smbldap_state);
- talloc_destroy(ldap_state.mem_ctx);
-
- DEBUG(5,("The connection to the LDAP server was closed\n"));
- /* maybe free the results here --metze */
-
- return NT_STATUS_OK;
-}
-
-
-/* This function doesn't make as much sense in an LDAP world since the calling
- node doesn't really control the ID ranges */
-static void ldap_idmap_status(void)
-{
- DEBUG(0, ("LDAP IDMAP Status not available\n"));
-}
-
-static struct idmap_methods ldap_methods = {
- ldap_idmap_init,
- ldap_allocate_id,
- ldap_get_sid_from_id,
- ldap_get_id_from_sid,
- ldap_set_mapping,
- ldap_idmap_close,
- ldap_idmap_status
-
-};
-
-NTSTATUS idmap_ldap_init(void)
-{
- return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &ldap_methods);
-}
diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c
deleted file mode 100644
index 58838512a68..00000000000
--- a/source/sam/idmap_rid.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * idmap_rid: static map between Active Directory/NT RIDs and RFC 2307 accounts
- * Copyright (C) Guenther Deschner, 2004
- * Copyright (C) Sumit Bose, 2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-NTSTATUS init_module(void);
-
-struct dom_entry {
- fstring name;
- fstring sid;
- uint32 min_id;
- uint32 max_id;
-};
-
-typedef struct trust_dom_array {
- int number;
- struct dom_entry *dom;
-} trust_dom_array;
-
-static trust_dom_array trust;
-
-static NTSTATUS rid_idmap_parse(const char *init_param,
- uint32 num_domains,
- fstring *domain_names,
- DOM_SID *domain_sids,
- uid_t u_low,
- uid_t u_high)
-{
- const char *p;
- int i;
- fstring sid_str;
- BOOL known_domain = False;
- fstring tok;
-
- p = init_param;
- trust.number = 0;
-
- /* falling back to automatic mapping when there were no options given */
- if (!*init_param) {
-
- DEBUG(3,("rid_idmap_parse: no domain list given or trusted domain-support deactivated, falling back to automatic mapping for own domain:\n"));
-
- sid_to_string(sid_str, &domain_sids[0]);
-
- fstrcpy(trust.dom[0].name, domain_names[0]);
- fstrcpy(trust.dom[0].sid, sid_str);
- trust.dom[0].min_id = u_low;
- trust.dom[0].max_id = u_high;
- trust.number = 1;
-
- DEBUGADD(3,("rid_idmap_parse:\tdomain: [%s], sid: [%s], range=[%d-%d]\n",
- trust.dom[0].name, trust.dom[0].sid, trust.dom[0].min_id, trust.dom[0].max_id));
- return NT_STATUS_OK;
- }
-
- /* scan through the init_param-list */
- while (next_token(&init_param, tok, LIST_SEP, sizeof(tok))) {
-
- p = tok;
- DEBUG(3,("rid_idmap_parse: parsing entry: %d\n", trust.number));
-
- /* reinit sizes */
- trust.dom = SMB_REALLOC_ARRAY(trust.dom, struct dom_entry,
- trust.number+1);
-
- if ( trust.dom == NULL ) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!next_token(&p, tok, "=", sizeof(tok))) {
- DEBUG(0, ("rid_idmap_parse: no '=' sign found in domain list [%s]\n", init_param));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* add the name */
- fstrcpy(trust.dom[trust.number].name, tok);
- DEBUGADD(3,("rid_idmap_parse:\tentry %d has name: [%s]\n", trust.number, trust.dom[trust.number].name));
-
- /* add the domain-sid */
- for (i=0; i<num_domains; i++) {
-
- known_domain = False;
-
- if (strequal(domain_names[i], trust.dom[trust.number].name)) {
-
- sid_to_string(sid_str, &domain_sids[i]);
- fstrcpy(trust.dom[trust.number].sid, sid_str);
-
- DEBUGADD(3,("rid_idmap_parse:\tentry %d has sid: [%s]\n", trust.number, trust.dom[trust.number].sid));
- known_domain = True;
- break;
- }
- }
-
- if (!known_domain) {
- DEBUG(0,("rid_idmap_parse: your DC does not know anything about domain: [%s]\n", trust.dom[trust.number].name));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!next_token(&p, tok, "-", sizeof(tok))) {
- DEBUG(0,("rid_idmap_parse: no mapping-range defined\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* add min_id */
- trust.dom[trust.number].min_id = atoi(tok);
- DEBUGADD(3,("rid_idmap_parse:\tentry %d has min_id: [%d]\n", trust.number, trust.dom[trust.number].min_id));
-
- /* add max_id */
- trust.dom[trust.number].max_id = atoi(p);
- DEBUGADD(3,("rid_idmap_parse:\tentry %d has max_id: [%d]\n", trust.number, trust.dom[trust.number].max_id));
-
- trust.number++;
- }
-
- return NT_STATUS_OK;
-
-}
-
-static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_names, DOM_SID **domain_sids)
-{
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- struct cli_state *cli;
- struct rpc_pipe_client *pipe_hnd;
- TALLOC_CTX *mem_ctx;
- POLICY_HND pol;
- uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
- fstring dc_name;
- struct in_addr dc_ip;
- const char *password = NULL;
- const char *username = NULL;
- const char *domain = NULL;
- uint32 info_class = 5;
- char *domain_name = NULL;
- DOM_SID *domain_sid, sid;
- fstring sid_str;
- int i;
- uint32 trusted_num_domains = 0;
- char **trusted_domain_names;
- DOM_SID *trusted_domain_sids;
- uint32 enum_ctx = 0;
- int own_domains = 2;
-
- /* put the results together */
- *num_domains = 2;
- *domain_names = SMB_MALLOC_ARRAY(fstring, *num_domains);
- *domain_sids = SMB_MALLOC_ARRAY(DOM_SID, *num_domains);
-
- /* avoid calling a DC when trusted domains are not allowed anyway */
- if (!lp_allow_trusted_domains()) {
-
- fstrcpy((*domain_names)[0], lp_workgroup());
- if (!secrets_fetch_domain_sid(lp_workgroup(), &sid)) {
- DEBUG(0,("rid_idmap_get_domains: failed to retrieve domain sid\n"));
- return status;
- }
- sid_copy(&(*domain_sids)[0], &sid);
-
- /* add BUILTIN */
- fstrcpy((*domain_names)[1], "BUILTIN");
- sid_copy(&(*domain_sids)[1], &global_sid_Builtin);
-
- return NT_STATUS_OK;
- }
-
- /* create mem_ctx */
- if (!(mem_ctx = talloc_init("rid_idmap_get_trusted_domains"))) {
- DEBUG(0, ("rid_idmap_get_domains: talloc_init() failed\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!get_dc_name(lp_workgroup(), 0, dc_name, &dc_ip)) {
- DEBUG(1, ("rid_idmap_get_domains: could not get dc-name\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* open a connection to the dc */
- username = secrets_fetch(SECRETS_AUTH_USER, NULL);
- password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
- domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
-
- if (username) {
-
- if (!domain)
- domain = smb_xstrdup(lp_workgroup());
-
- if (!password)
- password = smb_xstrdup("");
-
- DEBUG(3, ("rid_idmap_get_domains: IPC$ connections done by user %s\\%s\n", domain, username));
-
- } else {
-
- DEBUG(3, ("rid_idmap_get_domains: IPC$ connections done anonymously\n"));
- username = "";
- domain = "";
- password = "";
- }
-
- DEBUG(10, ("rid_idmap_get_domains: opening connection to [%s]\n", dc_name));
-
- status = cli_full_connection(&cli, global_myname(), dc_name,
- NULL, 0,
- "IPC$", "IPC",
- username,
- lp_workgroup(),
- password,
- CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, True, NULL);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("rid_idmap_get_domains: could not setup connection to dc\n"));
- return status;
- }
-
- /* query the lsa-pipe */
- pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("rid_idmap_get_domains: could not setup connection to dc\n"));
- goto out;
- }
-
- /* query policies */
- status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False, des_access,
- &pol);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &pol,
- info_class, &domain_name,
- &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("rid_idmap_get_domains: cannot retrieve domain-info\n"));
- goto out;
- }
-
- sid_to_string(sid_str, domain_sid);
- DEBUG(10,("rid_idmap_get_domains: my domain: [%s], sid: [%s]\n", domain_name, sid_str));
-
- /* scan trusted domains */
- DEBUG(10, ("rid_idmap_get_domains: enumerating trusted domains\n"));
- status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &pol, &enum_ctx,
- &trusted_num_domains,
- &trusted_domain_names,
- &trusted_domain_sids);
-
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) &&
- !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
- DEBUG(1, ("rid_idmap_get_domains: could not enumerate trusted domains\n"));
- goto out;
- }
-
- /* show trusted domains */
- DEBUG(10,("rid_idmap_get_domains: scan for trusted domains gave %d results:\n", trusted_num_domains));
- for (i=0; i<trusted_num_domains; i++) {
- sid_to_string(sid_str, &trusted_domain_sids[i]);
- DEBUGADD(10,("rid_idmap_get_domains:\t#%d\tDOMAIN: [%s], SID: [%s]\n",
- i, trusted_domain_names[i], sid_str));
- }
-
- if (!sid_equal(domain_sid, get_global_sam_sid()))
- ++own_domains;
-
- /* put the results together */
- *num_domains = trusted_num_domains + own_domains;
- *domain_names = SMB_REALLOC_ARRAY(*domain_names, fstring,
- *num_domains);
- if (!*domain_names) {
- goto out;
- }
- *domain_sids = SMB_REALLOC_ARRAY(*domain_sids, DOM_SID, *num_domains);
- if (!*domain_sids) {
- goto out;
- }
-
- /* first add mydomain */
- fstrcpy((*domain_names)[0], domain_name);
- sid_copy(&(*domain_sids)[0], domain_sid);
-
- /* then add BUILTIN */
- fstrcpy((*domain_names)[1], "BUILTIN");
- sid_copy(&(*domain_sids)[1], &global_sid_Builtin);
-
- /* then add my local sid */
- if (!sid_equal(domain_sid, get_global_sam_sid())) {
- fstrcpy((*domain_names)[2], global_myname());
- sid_copy(&(*domain_sids)[2], get_global_sam_sid());
- }
-
- /* add trusted domains */
- for (i=0; i<trusted_num_domains; i++) {
- fstrcpy((*domain_names)[i+own_domains], trusted_domain_names[i]);
- sid_copy(&((*domain_sids)[i+own_domains]), &(trusted_domain_sids[i]));
- }
-
- /* show complete domain list */
- DEBUG(5,("rid_idmap_get_domains: complete domain-list has %d entries:\n", *num_domains));
- for (i=0; i<*num_domains; i++) {
- sid_to_string(sid_str, &((*domain_sids)[i]));
- DEBUGADD(5,("rid_idmap_get_domains:\t#%d\tdomain: [%s], sid: [%s]\n",
- i, (*domain_names)[i], sid_str ));
- }
-
- status = NT_STATUS_OK;
-
-out:
- rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
- cli_rpc_pipe_close(pipe_hnd);
- talloc_destroy(mem_ctx);
- cli_shutdown(cli);
-
- return status;
-}
-
-static NTSTATUS rid_idmap_init(char *init_param)
-{
- int i, j;
- uid_t u_low, u_high;
- gid_t g_low, g_high;
- uint32 num_domains = 0;
- fstring *domain_names;
- DOM_SID *domain_sids;
- NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
- trust.dom = NULL;
-
- /* basic sanity checks */
- if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
- DEBUG(0, ("rid_idmap_init: cannot get required global idmap-ranges.\n"));
- return nt_status;
- }
-
- if (u_low != g_low || u_high != g_high) {
- DEBUG(0, ("rid_idmap_init: range defined in \"idmap uid\" must match range of \"idmap gid\".\n"));
- return nt_status;
- }
-
- if (lp_allow_trusted_domains()) {
-#if IDMAP_RID_SUPPORT_TRUSTED_DOMAINS
- DEBUG(3,("rid_idmap_init: enabling trusted-domain-mapping\n"));
-#else
- DEBUG(0,("rid_idmap_init: idmap_rid does not work with trusted domains\n"));
- DEBUGADD(0,("rid_idmap_init: please set \"allow trusted domains\" to \"no\" when using idmap_rid\n"));
- return nt_status;
-#endif
- }
-
- /* init sizes */
- trust.dom = SMB_MALLOC_P(struct dom_entry);
- if (trust.dom == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* retrieve full domain list */
- nt_status = rid_idmap_get_domains(&num_domains, &domain_names, &domain_sids);
- if (!NT_STATUS_IS_OK(nt_status) &&
- !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES) &&
- !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)) {
- DEBUG(0, ("rid_idmap_init: cannot fetch sids for domain and/or trusted-domains from domain-controller.\n"));
- return nt_status;
- }
-
- /* parse the init string */
- nt_status = rid_idmap_parse(init_param, num_domains, domain_names, domain_sids, u_low, u_high);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(0, ("rid_idmap_init: cannot parse module-configuration\n"));
- goto out;
- }
-
- nt_status = NT_STATUS_INVALID_PARAMETER;
-
- /* some basic sanity checks */
- for (i=0; i<trust.number; i++) {
-
- if (trust.dom[i].min_id > trust.dom[i].max_id) {
- DEBUG(0, ("rid_idmap_init: min_id (%d) has to be smaller than max_id (%d) for domain [%s]\n",
- trust.dom[i].min_id, trust.dom[i].max_id, trust.dom[i].name));
- goto out;
- }
-
- if (trust.dom[i].min_id < u_low || trust.dom[i].max_id > u_high) {
- DEBUG(0, ("rid_idmap_init: mapping of domain [%s] (%d-%d) has to fit into global idmap range (%d-%d).\n",
- trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id, u_low, u_high));
- goto out;
- }
- }
-
- /* check for overlaps */
- for (i=0; i<trust.number-1; i++) {
- for (j=i+1; j<trust.number; j++) {
- if (trust.dom[i].min_id <= trust.dom[j].max_id && trust.dom[j].min_id <= trust.dom[i].max_id) {
- DEBUG(0, ("rid_idmap_init: the ranges of domain [%s] and [%s] overlap\n",
- trust.dom[i+1].name, trust.dom[i].name));
- goto out;
- }
- }
- }
-
- DEBUG(3, ("rid_idmap_init: using %d mappings:\n", trust.number));
- for (i=0; i<trust.number; i++) {
- DEBUGADD(3, ("rid_idmap_init:\tdomain: [%s], sid: [%s], min_id: [%d], max_id: [%d]\n",
- trust.dom[i].name, trust.dom[i].sid, trust.dom[i].min_id, trust.dom[i].max_id));
- }
-
- nt_status = NT_STATUS_OK;
-
-out:
- SAFE_FREE(domain_names);
- SAFE_FREE(domain_sids);
-
- return nt_status;
-}
-
-static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
-{
- fstring sid_string;
- int i;
- DOM_SID sidstr;
-
- /* find range */
- for (i=0; i<trust.number; i++) {
- if (trust.dom[i].min_id <= unid.uid && trust.dom[i].max_id >= unid.uid )
- break;
- }
-
- if (i == trust.number) {
- DEBUG(0,("rid_idmap_get_sid_from_id: no suitable range available for id: %d\n", unid.uid));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* use lower-end of idmap-range as offset for users and groups*/
- unid.uid -= trust.dom[i].min_id;
-
- if (!trust.dom[i].sid)
- return NT_STATUS_INVALID_PARAMETER;
-
- string_to_sid(&sidstr, trust.dom[i].sid);
- sid_copy(sid, &sidstr);
- if (!sid_append_rid( sid, (unsigned long)unid.uid )) {
- DEBUG(0,("rid_idmap_get_sid_from_id: could not append rid to domain sid\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- DEBUG(3, ("rid_idmap_get_sid_from_id: mapped POSIX %s %d to SID [%s]\n",
- (id_type == ID_GROUPID) ? "GID" : "UID", unid.uid,
- sid_to_string(sid_string, sid)));
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid)
-{
- fstring sid_string;
- int i;
- uint32 rid;
- DOM_SID sidstr;
-
- /* check if we have a mapping for the sid */
- for (i=0; i<trust.number; i++) {
- if (!trust.dom[i].sid) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- string_to_sid(&sidstr, trust.dom[i].sid);
- if ( sid_compare_domain(sid, &sidstr) == 0 )
- break;
- }
-
- if (i == trust.number) {
- DEBUG(0,("rid_idmap_get_id_from_sid: no suitable range available for sid: %s\n",
- sid_string_static(sid)));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!sid_peek_rid(sid, &rid)) {
- DEBUG(0,("rid_idmap_get_id_from_sid: could not peek rid\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* use lower-end of idmap-range as offset for users and groups */
- unid->uid = rid + trust.dom[i].min_id;
-
- if (unid->uid > trust.dom[i].max_id) {
- DEBUG(0,("rid_idmap_get_id_from_sid: rid: %d (%s: %d) too high for mapping of domain: %s (%d-%d)\n",
- rid, (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid, trust.dom[i].name,
- trust.dom[i].min_id, trust.dom[i].max_id));
- return NT_STATUS_INVALID_PARAMETER;
- }
- if (unid->uid < trust.dom[i].min_id) {
- DEBUG(0,("rid_idmap_get_id_from_sid: rid: %d (%s: %d) too low for mapping of domain: %s (%d-%d)\n",
- rid, (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid,
- trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG(3,("rid_idmap_get_id_from_sid: mapped SID [%s] to POSIX %s %d\n",
- sid_to_string(sid_string, sid),
- (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid));
-
- return NT_STATUS_OK;
-
-}
-
-static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS rid_idmap_close(void)
-{
- SAFE_FREE(trust.dom);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static void rid_idmap_status(void)
-{
- DEBUG(0, ("RID IDMAP Status not available\n"));
-}
-
-static struct idmap_methods rid_methods = {
- rid_idmap_init,
- rid_idmap_allocate_id,
- rid_idmap_get_sid_from_id,
- rid_idmap_get_id_from_sid,
- rid_idmap_set_mapping,
- rid_idmap_close,
- rid_idmap_status
-};
-
-NTSTATUS init_module(void)
-{
- return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rid", &rid_methods);
-}
-
diff --git a/source/sam/idmap_smbldap.c b/source/sam/idmap_smbldap.c
deleted file mode 100644
index 4d80364437c..00000000000
--- a/source/sam/idmap_smbldap.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- idmap LDAP backend
-
- Copyright (C) Tim Potter 2000
- Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
- Copyright (C) Simo Sorce 2003
- Copyright (C) Gerald Carter 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-struct ldap_connection *ldap_conn = NULL;
-
-/* number tries while allocating new id */
-#define LDAP_MAX_ALLOC_ID 128
-
-
-/***********************************************************************
- This function cannot be called to modify a mapping, only set a new one
-***********************************************************************/
-
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- pstring id_str;
- const char *type;
- fstring sid_string;
- struct ldap_message *msg;
- struct ldap_message *mod_res = NULL;
- char *mod;
-
- type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
-
- sid_to_string( sid_string, sid );
-
- pstr_sprintf(id_str, "%lu",
- ((id_type & ID_USERID) ?
- (unsigned long)id.uid : (unsigned long)id.gid));
-
- asprintf(&mod,
- "dn: sambaSID=%s,%s\n"
- "changetype: add\n"
- "objectClass: sambaIdmapEntry\n"
- "objectClass: sambaSidEntry\n"
- "sambaSID: %s\n"
- "%s: %lu\n",
- sid_string, lp_ldap_idmap_suffix(), sid_string, type,
- ((id_type & ID_USERID) ?
- (unsigned long)id.uid : (unsigned long)id.gid));
-
- msg = ldap_ldif2msg(mod);
-
- SAFE_FREE(mod);
-
- if (msg == NULL)
- return NT_STATUS_NO_MEMORY;
-
- mod_res = ldap_transaction(ldap_conn, msg);
-
- if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0))
- goto out;
-
- ret = NT_STATUS_OK;
- out:
- destroy_ldap_message(msg);
- destroy_ldap_message(mod_res);
- return ret;
-}
-
-/*****************************************************************************
- Allocate a new uid or gid
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- uid_t luid, huid;
- gid_t lgid, hgid;
- const char *attrs[] = { "uidNumber", "gidNumber" };
- struct ldap_message *idpool_s = NULL;
- struct ldap_message *idpool = NULL;
- struct ldap_message *mod_msg = NULL;
- struct ldap_message *mod_res = NULL;
- int value;
- const char *id_attrib;
- char *mod;
-
- id_attrib = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
-
- idpool_s = new_ldap_search_message(lp_ldap_suffix(),
- LDAP_SEARCH_SCOPE_SUB,
- "(objectclass=sambaUnixIdPool)",
- 2, attrs);
-
- if (idpool_s == NULL)
- return NT_STATUS_NO_MEMORY;
-
- idpool = ldap_searchone(ldap_conn, idpool_s, NULL);
-
- if (idpool == NULL)
- goto out;
-
- if (!ldap_find_single_int(idpool, id_attrib, &value))
- goto out;
-
- /* this must succeed or else we wouldn't have initialized */
-
- lp_idmap_uid( &luid, &huid);
- lp_idmap_gid( &lgid, &hgid);
-
- /* make sure we still have room to grow */
-
- if (id_type & ID_USERID) {
- id->uid = value;
- if (id->uid > huid ) {
- DEBUG(0,("ldap_allocate_id: Cannot allocate uid "
- "above %lu!\n", (unsigned long)huid));
- goto out;
- }
- }
- else {
- id->gid = value;
- if (id->gid > hgid ) {
- DEBUG(0,("ldap_allocate_id: Cannot allocate gid "
- "above %lu!\n", (unsigned long)hgid));
- goto out;
- }
- }
-
- asprintf(&mod,
- "dn: %s\n"
- "changetype: modify\n"
- "delete: %s\n"
- "%s: %d\n"
- "-\n"
- "add: %s\n"
- "%s: %d\n",
- idpool->r.SearchResultEntry.dn, id_attrib, id_attrib, value,
- id_attrib, id_attrib, value+1);
-
- mod_msg = ldap_ldif2msg(mod);
-
- SAFE_FREE(mod);
-
- if (mod_msg == NULL)
- goto out;
-
- mod_res = ldap_transaction(ldap_conn, mod_msg);
-
- if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0))
- goto out;
-
- ret = NT_STATUS_OK;
-out:
- destroy_ldap_message(idpool_s);
- destroy_ldap_message(idpool);
- destroy_ldap_message(mod_msg);
- destroy_ldap_message(mod_res);
-
- return ret;
-}
-
-/*****************************************************************************
- get a sid from an id
-*****************************************************************************/
-
-static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
-{
- pstring filter;
- const char *type;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- const char *attr_list[] = { "sambaSID" };
- struct ldap_message *msg;
- struct ldap_message *entry = NULL;
- char *sid_str;
-
- type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
-
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", "sambaIdmapEntry",
- type,
- ((id_type & ID_USERID) ?
- (unsigned long)id.uid : (unsigned long)id.gid));
-
- msg = new_ldap_search_message(lp_ldap_idmap_suffix(),
- LDAP_SEARCH_SCOPE_SUB,
- filter, 1, attr_list);
-
- if (msg == NULL)
- return NT_STATUS_NO_MEMORY;
-
- entry = ldap_searchone(ldap_conn, msg, NULL);
-
- if (entry == NULL)
- goto out;
-
- if (!ldap_find_single_string(entry, "sambaSID", entry->mem_ctx,
- &sid_str))
- goto out;
-
- if (!string_to_sid(sid, sid_str))
- goto out;
-
- ret = NT_STATUS_OK;
-out:
- destroy_ldap_message(msg);
- destroy_ldap_message(entry);
-
- return ret;
-}
-
-/***********************************************************************
- Get an id from a sid
-***********************************************************************/
-
-static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type,
- const DOM_SID *sid)
-{
- pstring filter;
- const char *type;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldap_message *msg;
- struct ldap_message *entry = NULL;
- int i;
-
- DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_string_static(sid),
- (*id_type & ID_GROUPID ? "group" : "user") ));
-
- type = ((*id_type) & ID_USERID) ? "uidNumber" : "gidNumber";
-
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
- "sambaIdmapEntry", "sambaSID", sid_string_static(sid));
-
- msg = new_ldap_search_message(lp_ldap_idmap_suffix(),
- LDAP_SEARCH_SCOPE_SUB,
- filter, 1, &type);
-
- if (msg == NULL)
- return NT_STATUS_NO_MEMORY;
-
- entry = ldap_searchone(ldap_conn, msg, NULL);
-
- if (entry != NULL) {
- int value;
-
- if (!ldap_find_single_int(entry, type, &value))
- goto out;
-
- if ((*id_type) & ID_USERID)
- id->uid = value;
- else
- id->gid = value;
-
- ret = NT_STATUS_OK;
- goto out;
- }
-
- if ((*id_type) & ID_QUERY_ONLY)
- goto out;
-
- /* Allocate a new RID */
-
- for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
- ret = ldap_allocate_id(id, *id_type);
- if ( NT_STATUS_IS_OK(ret) )
- break;
- }
-
- if ( !NT_STATUS_IS_OK(ret) ) {
- DEBUG(0,("Could not allocate id\n"));
- goto out;
- }
-
- DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
- (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid ));
-
- ret = ldap_set_mapping(sid, *id, *id_type);
-
-out:
- destroy_ldap_message(msg);
- destroy_ldap_message(entry);
-
- return ret;
-}
-
-/**********************************************************************
- Verify the sambaUnixIdPool entry in the directory.
-**********************************************************************/
-static NTSTATUS verify_idpool(void)
-{
- const char *attr_list[3] = { "uidnumber", "gidnumber", "objectclass" };
- BOOL result;
- char *mod;
- struct ldap_message *msg, *entry, *res;
-
- uid_t luid, huid;
- gid_t lgid, hgid;
-
- msg = new_ldap_search_message(lp_ldap_suffix(),
- LDAP_SEARCH_SCOPE_SUB,
- "(objectClass=sambaUnixIdPool)",
- 3, attr_list);
-
- if (msg == NULL)
- return NT_STATUS_NO_MEMORY;
-
- entry = ldap_searchone(ldap_conn, msg, NULL);
-
- result = (entry != NULL);
-
- destroy_ldap_message(msg);
- destroy_ldap_message(entry);
-
- if (result)
- return NT_STATUS_OK;
-
- if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) {
- DEBUG(3,("ldap_idmap_init: idmap uid/gid parameters not "
- "specified\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- asprintf(&mod,
- "dn: %s\n"
- "changetype: modify\n"
- "add: objectClass\n"
- "objectClass: sambaUnixIdPool\n"
- "-\n"
- "add: uidNumber\n"
- "uidNumber: %lu\n"
- "-\n"
- "add: gidNumber\n"
- "gidNumber: %lu\n",
- lp_ldap_idmap_suffix(),
- (unsigned long)luid, (unsigned long)lgid);
-
- msg = ldap_ldif2msg(mod);
-
- SAFE_FREE(mod);
-
- if (msg == NULL)
- return NT_STATUS_NO_MEMORY;
-
- res = ldap_transaction(ldap_conn, msg);
-
- if ((res == NULL) || (res->r.ModifyResponse.resultcode != 0)) {
- destroy_ldap_message(msg);
- destroy_ldap_message(res);
- DEBUG(5, ("Could not add sambaUnixIdPool\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- destroy_ldap_message(msg);
- destroy_ldap_message(res);
- return NT_STATUS_OK;
-}
-
-/*****************************************************************************
- Initialise idmap database.
-*****************************************************************************/
-
-static NTSTATUS ldap_idmap_init( char *params )
-{
- NTSTATUS nt_status;
- char *dn, *pw;
-
- ldap_conn = new_ldap_connection();
-
- if (!fetch_ldap_pw(&dn, &pw))
- return NT_STATUS_UNSUCCESSFUL;
-
- ldap_conn->auth_dn = talloc_strdup(ldap_conn->mem_ctx, dn);
- ldap_conn->simple_pw = talloc_strdup(ldap_conn->mem_ctx, pw);
-
- SAFE_FREE(dn);
- SAFE_FREE(pw);
-
- if (!ldap_setup_connection(ldap_conn, params, NULL, NULL))
- return NT_STATUS_UNSUCCESSFUL;
-
- /* see if the idmap suffix and sub entries exists */
-
- nt_status = verify_idpool();
- if ( !NT_STATUS_IS_OK(nt_status) )
- return nt_status;
-
- return NT_STATUS_OK;
-}
-
-/*****************************************************************************
- End the LDAP session
-*****************************************************************************/
-
-static NTSTATUS ldap_idmap_close(void)
-{
-
- DEBUG(5,("The connection to the LDAP server was closed\n"));
- /* maybe free the results here --metze */
-
- return NT_STATUS_OK;
-}
-
-
-/* This function doesn't make as much sense in an LDAP world since the calling
- node doesn't really control the ID ranges */
-static void ldap_idmap_status(void)
-{
- DEBUG(0, ("LDAP IDMAP Status not available\n"));
-}
-
-static struct idmap_methods ldap_methods = {
- ldap_idmap_init,
- ldap_allocate_id,
- ldap_get_sid_from_id,
- ldap_get_id_from_sid,
- ldap_set_mapping,
- ldap_idmap_close,
- ldap_idmap_status
-
-};
-
-NTSTATUS idmap_smbldap_init(void)
-{
- return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "smbldap", &ldap_methods);
-}
diff --git a/source/sam/idmap_tdb.c b/source/sam/idmap_tdb.c
deleted file mode 100644
index 665c56d2f67..00000000000
--- a/source/sam/idmap_tdb.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- idmap TDB backend
-
- Copyright (C) Tim Potter 2000
- Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
- Copyright (C) Simo Sorce 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-/* High water mark keys */
-#define HWM_GROUP "GROUP HWM"
-#define HWM_USER "USER HWM"
-
-/* Globals */
-static TDB_CONTEXT *idmap_tdb;
-
-static struct idmap_state {
-
- /* User and group id pool */
-
- uid_t uid_low, uid_high; /* Range of uids to allocate */
- gid_t gid_low, gid_high; /* Range of gids to allocate */
-} idmap_state;
-
-/**********************************************************************
- Allocate either a user or group id from the pool
-**********************************************************************/
-
-static NTSTATUS db_allocate_id(unid_t *id, int id_type)
-{
- BOOL ret;
- int hwm;
-
- if (!id)
- return NT_STATUS_INVALID_PARAMETER;
-
- /* Get current high water mark */
- switch (id_type & ID_TYPEMASK) {
- case ID_USERID:
-
- if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
-
- /* check it is in the range */
- if (hwm > idmap_state.uid_high) {
- DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n",
- (unsigned long)idmap_state.uid_high));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* fetch a new id and increment it */
- ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, (unsigned int *)&hwm, 1);
- if (!ret) {
- DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* recheck it is in the range */
- if (hwm > idmap_state.uid_high) {
- DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n",
- (unsigned long)idmap_state.uid_high));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- (*id).uid = hwm;
- DEBUG(10,("db_allocate_id: ID_USERID (*id).uid = %d\n", (unsigned int)hwm));
-
- break;
- case ID_GROUPID:
- if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
-
- /* check it is in the range */
- if (hwm > idmap_state.gid_high) {
- DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n",
- (unsigned long)idmap_state.gid_high));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* fetch a new id and increment it */
- ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, (unsigned int *)&hwm, 1);
-
- if (!ret) {
- DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* recheck it is in the range */
- if (hwm > idmap_state.gid_high) {
- DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n",
- (unsigned long)idmap_state.gid_high));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- (*id).gid = hwm;
- DEBUG(10,("db_allocate_id: ID_GROUPID (*id).gid = %d\n", (unsigned int)hwm));
-
- break;
- default:
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return NT_STATUS_OK;
-}
-
-/* Get a sid from an id */
-static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
-{
- TDB_DATA key, data;
- fstring keystr;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if (!sid)
- return NT_STATUS_INVALID_PARAMETER;
-
- switch (id_type & ID_TYPEMASK) {
- case ID_USERID:
- slprintf(keystr, sizeof(keystr), "UID %lu", (unsigned long)id.uid);
- break;
- case ID_GROUPID:
- slprintf(keystr, sizeof(keystr), "GID %lu", (unsigned long)id.gid);
- break;
- default:
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- key.dptr = keystr;
- key.dsize = strlen(keystr) + 1;
-
- DEBUG(10,("internal_get_sid_from_id: fetching record %s\n", keystr ));
-
- data = tdb_fetch(idmap_tdb, key);
-
- if (data.dptr) {
- if (string_to_sid(sid, data.dptr)) {
- DEBUG(10,("internal_get_sid_from_id: fetching record %s -> %s\n", keystr, data.dptr ));
- ret = NT_STATUS_OK;
- }
- SAFE_FREE(data.dptr);
- }
-
- return ret;
-}
-
-/* Error codes for get_id_from_sid */
-enum getidfromsiderr { GET_ID_FROM_SID_OK = 0, GET_ID_FROM_SID_NOTFOUND, GET_ID_FROM_SID_WRONG_TYPE, GET_ID_FROM_SID_ERR };
-
-static enum getidfromsiderr internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
-{
- enum getidfromsiderr ret = GET_ID_FROM_SID_ERR;
- fstring keystr;
- TDB_DATA key, data;
- int type = *id_type & ID_TYPEMASK;
-
- /* Check if sid is present in database */
- sid_to_string(keystr, sid);
-
- key.dptr = keystr;
- key.dsize = strlen(keystr) + 1;
-
- DEBUG(10,("internal_get_id_from_sid: fetching record %s of type 0x%x\n", keystr, type ));
-
- data = tdb_fetch(idmap_tdb, key);
- if (!data.dptr) {
- DEBUG(10,("internal_get_id_from_sid: record %s not found\n", keystr ));
- return GET_ID_FROM_SID_NOTFOUND;
- } else {
- DEBUG(10,("internal_get_id_from_sid: record %s -> %s\n", keystr, data.dptr ));
- }
-
- if (type == ID_EMPTY || type == ID_USERID) {
- fstring scanstr;
- /* Parse and return existing uid */
- fstrcpy(scanstr, "UID %d");
-
- if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) {
- /* uid ok? */
- if (type == ID_EMPTY) {
- *id_type = ID_USERID;
- }
- DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n",
- (type == ID_EMPTY) ? "ID_EMPTY" : "ID_USERID",
- keystr, data.dptr ));
- ret = GET_ID_FROM_SID_OK;
- } else {
- ret = GET_ID_FROM_SID_WRONG_TYPE;
- }
- }
-
- if ((ret != GET_ID_FROM_SID_OK) && (type == ID_EMPTY || type == ID_GROUPID)) {
- fstring scanstr;
- /* Parse and return existing gid */
- fstrcpy(scanstr, "GID %d");
-
- if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) {
- /* gid ok? */
- if (type == ID_EMPTY) {
- *id_type = ID_GROUPID;
- }
- DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n",
- (type == ID_EMPTY) ? "ID_EMPTY" : "ID_GROUPID",
- keystr, data.dptr ));
- ret = GET_ID_FROM_SID_OK;
- } else {
- ret = GET_ID_FROM_SID_WRONG_TYPE;
- }
- }
-
- SAFE_FREE(data.dptr);
-
- return ret;
-}
-
-/* Get a sid from an id */
-static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- enum getidfromsiderr iderr;
- int id_type = id_type_in & ID_TYPEMASK;
- unid_t id_tmp = id;
- int id_type_tmp = id_type;
-
- DEBUG(10,("db_get_sid_from_id: id_type_in = 0x%x\n", id_type_in));
-
- ret = internal_get_sid_from_id(sid, id, id_type);
- if (!NT_STATUS_IS_OK(ret)) {
- return ret;
- }
-
- iderr = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid);
- if (iderr != GET_ID_FROM_SID_OK) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (id_type_tmp != id_type) {
- return NT_STATUS_UNSUCCESSFUL;
- } else if (id_type == ID_USERID) {
- if (id_tmp.uid != id.uid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- } else if (id_type == ID_GROUPID) {
- if (id_tmp.gid != id.gid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- } else {
- return NT_STATUS_UNSUCCESSFUL;
- }
- return ret;
-}
-/* Get an id from a sid */
-static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- enum getidfromsiderr iderr;
-
- DEBUG(10,("db_get_id_from_sid\n"));
-
- if (!sid || !id || !id_type)
- return NT_STATUS_INVALID_PARAMETER;
-
- iderr = internal_get_id_from_sid(id, id_type, sid);
- if (iderr == GET_ID_FROM_SID_OK) {
- DOM_SID sid_tmp;
- ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type);
- if (NT_STATUS_IS_OK(ret)) {
- if (!sid_equal(&sid_tmp, sid)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
- } else if (iderr == GET_ID_FROM_SID_WRONG_TYPE) {
- /* We found a record but not the type we wanted.
- * This is an error, not an opportunity to overwrite...
- * JRA.
- */
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!(*id_type & ID_QUERY_ONLY) && (iderr != GET_ID_FROM_SID_OK) &&
- (((*id_type & ID_TYPEMASK) == ID_USERID)
- || (*id_type & ID_TYPEMASK) == ID_GROUPID)) {
- TDB_DATA sid_data;
- TDB_DATA ugid_data;
- fstring sid_string;
-
- sid_to_string(sid_string, sid);
-
- sid_data.dptr = sid_string;
- sid_data.dsize = strlen(sid_string)+1;
-
- /* Lock the record for this SID. */
- if (tdb_chainlock(idmap_tdb, sid_data) != 0) {
- DEBUG(10,("db_get_id_from_sid: failed to lock record %s. Error %s\n",
- sid_string, tdb_errorstr(idmap_tdb) ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- do {
- fstring ugid_str;
-
- /* Allocate a new id for this sid */
- ret = db_allocate_id(id, *id_type);
- if (!NT_STATUS_IS_OK(ret))
- break;
-
- /* Store the UID side */
- /* Store new id */
- if (*id_type & ID_USERID) {
- slprintf(ugid_str, sizeof(ugid_str), "UID %lu",
- (unsigned long)((*id).uid));
- } else {
- slprintf(ugid_str, sizeof(ugid_str), "GID %lu",
- (unsigned long)((*id).gid));
- }
-
- ugid_data.dptr = ugid_str;
- ugid_data.dsize = strlen(ugid_str) + 1;
-
- DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n",
- ugid_data.dptr, sid_data.dptr ));
-
- if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) {
- ret = NT_STATUS_OK;
- break;
- }
- if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS)
- DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) ));
- ret = NT_STATUS_UNSUCCESSFUL;
- } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS);
-
- if (NT_STATUS_IS_OK(ret)) {
-
- DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n",
- sid_data.dptr, ugid_data.dptr ));
-
- if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) {
- DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) ));
- /* TODO: print tdb error !! */
- tdb_chainunlock(idmap_tdb, sid_data);
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
-
- tdb_chainunlock(idmap_tdb, sid_data);
- }
-
- return ret;
-}
-
-static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
-{
- TDB_DATA ksid, kid, data;
- fstring ksidstr;
- fstring kidstr;
-
- DEBUG(10,("db_set_mapping: id_type = 0x%x\n", id_type));
-
- if (!sid)
- return NT_STATUS_INVALID_PARAMETER;
-
- sid_to_string(ksidstr, sid);
-
- ksid.dptr = ksidstr;
- ksid.dsize = strlen(ksidstr) + 1;
-
- if (id_type & ID_USERID) {
- slprintf(kidstr, sizeof(kidstr), "UID %lu", (unsigned long)id.uid);
- } else if (id_type & ID_GROUPID) {
- slprintf(kidstr, sizeof(kidstr), "GID %lu", (unsigned long)id.gid);
- } else {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- kid.dptr = kidstr;
- kid.dsize = strlen(kidstr) + 1;
-
- /* *DELETE* prevoius mappings if any.
- * This is done both SID and [U|G]ID passed in */
-
- /* Lock the record for this SID. */
- if (tdb_chainlock(idmap_tdb, ksid) != 0) {
- DEBUG(10,("db_set_mapping: failed to lock record %s. Error %s\n",
- ksidstr, tdb_errorstr(idmap_tdb) ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(10,("db_set_mapping: fetching %s\n", ksid.dptr));
-
- data = tdb_fetch(idmap_tdb, ksid);
- if (data.dptr) {
- DEBUG(10,("db_set_mapping: deleting %s and %s\n", data.dptr, ksid.dptr ));
- tdb_delete(idmap_tdb, data);
- tdb_delete(idmap_tdb, ksid);
- SAFE_FREE(data.dptr);
- }
- data = tdb_fetch(idmap_tdb, kid);
- if (data.dptr) {
- DEBUG(10,("db_set_mapping: deleting %s and %s\n", data.dptr, kid.dptr ));
- tdb_delete(idmap_tdb, data);
- tdb_delete(idmap_tdb, kid);
- SAFE_FREE(data.dptr);
- }
-
- if (tdb_store(idmap_tdb, ksid, kid, TDB_INSERT) == -1) {
- DEBUG(0, ("idb_set_mapping: tdb_store 1 error: %s\n", tdb_errorstr(idmap_tdb)));
- tdb_chainunlock(idmap_tdb, ksid);
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (tdb_store(idmap_tdb, kid, ksid, TDB_INSERT) == -1) {
- DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb)));
- tdb_chainunlock(idmap_tdb, ksid);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- tdb_chainunlock(idmap_tdb, ksid);
- DEBUG(10,("db_set_mapping: stored %s -> %s and %s -> %s\n", ksid.dptr, kid.dptr, kid.dptr, ksid.dptr ));
- return NT_STATUS_OK;
-}
-
-/*****************************************************************************
- Initialise idmap database.
-*****************************************************************************/
-
-static NTSTATUS db_idmap_init( char *params )
-{
- SMB_STRUCT_STAT stbuf;
- char *tdbfile = NULL;
- int32 version;
- BOOL tdb_is_new = False;
-
- /* use the old database if present */
- tdbfile = SMB_STRDUP(lock_path("winbindd_idmap.tdb"));
- if (!tdbfile) {
- DEBUG(0, ("idmap_init: out of memory!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!file_exist(tdbfile, &stbuf)) {
- tdb_is_new = True;
- }
-
- DEBUG(10,("db_idmap_init: Opening tdbfile %s\n", tdbfile ));
-
- /* Open idmap repository */
- if (!(idmap_tdb = tdb_open_log(tdbfile, 0,
- TDB_DEFAULT, O_RDWR | O_CREAT,
- 0644))) {
- DEBUG(0, ("idmap_init: Unable to open idmap database\n"));
- SAFE_FREE(tdbfile);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- SAFE_FREE(tdbfile);
-
- if (tdb_is_new) {
- /* the file didn't existed before opening it, let's
- * store idmap version as nobody else yet opened and
- * stored it. I do not like this method but didn't
- * found a way to understand if an opened tdb have
- * been just created or not --- SSS */
- tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION);
- }
-
- /* check against earlier versions */
- version = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
- if (version != IDMAP_VERSION) {
- DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n"));
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
-
- /* Create high water marks for group and user id */
- if (!lp_idmap_uid(&idmap_state.uid_low, &idmap_state.uid_high)) {
- DEBUG(1, ("idmap uid range missing or invalid\n"));
- DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
- } else {
- if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) {
- if (tdb_store_int32(idmap_tdb, HWM_USER, idmap_state.uid_low) == -1) {
- DEBUG(0, ("idmap_init: Unable to initialise user hwm in idmap database\n"));
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
- }
- }
-
- if (!lp_idmap_gid(&idmap_state.gid_low, &idmap_state.gid_high)) {
- DEBUG(1, ("idmap gid range missing or invalid\n"));
- DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
- } else {
- if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) {
- if (tdb_store_int32(idmap_tdb, HWM_GROUP, idmap_state.gid_low) == -1) {
- DEBUG(0, ("idmap_init: Unable to initialise group hwm in idmap database\n"));
- return NT_STATUS_INTERNAL_DB_ERROR;
- }
- }
- }
-
- return NT_STATUS_OK;
-}
-
-/* Close the tdb */
-static NTSTATUS db_idmap_close(void)
-{
- if (idmap_tdb) {
- if (tdb_close(idmap_tdb) == 0) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
- return NT_STATUS_OK;
-}
-
-
-/* Dump status information to log file. Display different stuff based on
- the debug level:
-
- Debug Level Information Displayed
- =================================================================
- 0 Percentage of [ug]id range allocated
- 0 High water marks (next allocated ids)
-*/
-
-#define DUMP_INFO 0
-
-static void db_idmap_status(void)
-{
- int user_hwm, group_hwm;
-
- DEBUG(0, ("winbindd idmap status:\n"));
-
- /* Get current high water marks */
-
- if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
- DEBUG(DUMP_INFO,
- ("\tCould not get userid high water mark!\n"));
- }
-
- if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
- DEBUG(DUMP_INFO,
- ("\tCould not get groupid high water mark!\n"));
- }
-
- /* Display next ids to allocate */
-
- if (user_hwm != -1) {
- DEBUG(DUMP_INFO,
- ("\tNext userid to allocate is %d\n", user_hwm));
- }
-
- if (group_hwm != -1) {
- DEBUG(DUMP_INFO,
- ("\tNext groupid to allocate is %d\n", group_hwm));
- }
-
- /* Display percentage of id range already allocated. */
-
- if (user_hwm != -1) {
- int num_users = user_hwm - idmap_state.uid_low;
- int total_users =
- idmap_state.uid_high - idmap_state.uid_low;
-
- DEBUG(DUMP_INFO,
- ("\tUser id range is %d%% full (%d of %d)\n",
- num_users * 100 / total_users, num_users,
- total_users));
- }
-
- if (group_hwm != -1) {
- int num_groups = group_hwm - idmap_state.gid_low;
- int total_groups =
- idmap_state.gid_high - idmap_state.gid_low;
-
- DEBUG(DUMP_INFO,
- ("\tGroup id range is %d%% full (%d of %d)\n",
- num_groups * 100 / total_groups, num_groups,
- total_groups));
- }
-
- /* Display complete mapping of users and groups to rids */
-}
-
-/**********************************************************************
- Return the TDB_CONTEXT* for winbindd_idmap. I **really** feel
- dirty doing this, but not so dirty that I want to create another
- tdb
-***********************************************************************/
-
-TDB_CONTEXT *idmap_tdb_handle( void )
-{
- if ( idmap_tdb )
- return idmap_tdb;
-
- /* go ahead an open it; db_idmap_init() doesn't use any params
- right now */
-
- db_idmap_init( NULL );
- if ( idmap_tdb )
- return idmap_tdb;
-
- return NULL;
-}
-
-static struct idmap_methods db_methods = {
-
- db_idmap_init,
- db_allocate_id,
- db_get_sid_from_id,
- db_get_id_from_sid,
- db_set_mapping,
- db_idmap_close,
- db_idmap_status
-
-};
-
-NTSTATUS idmap_tdb_init(void)
-{
- return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods);
-}
diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c
deleted file mode 100644
index f78d3bdc233..00000000000
--- a/source/sam/idmap_util.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- ID Mapping
- Copyright (C) Simo Sorce 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-/*****************************************************************
- Returns SID pointer.
-*****************************************************************/
-
-NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid, int flags)
-{
- unid_t id;
-
- DEBUG(10,("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid));
-
- flags |= ID_USERID;
- id.uid = uid;
-
- return idmap_get_sid_from_id(sid, id, flags);
-}
-
-/*****************************************************************
- Group mapping is used for gids that maps to Wellknown SIDs
- Returns SID pointer.
-*****************************************************************/
-
-NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid, int flags)
-{
- unid_t id;
-
- DEBUG(10,("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid));
-
- flags |= ID_GROUPID;
- id.gid = gid;
-
- return idmap_get_sid_from_id(sid, id, flags);
-}
-
-/*****************************************************************
- if it is a foreign sid or it is in idmap rid range check idmap,
- otherwise falls back to the legacy algorithmic mapping.
- Returns True if this name is a user sid and the conversion
- was done correctly, False if not.
-*****************************************************************/
-
-NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- unid_t id;
-
- DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
-
- flags |= ID_USERID;
-
- ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
-
- if ( NT_STATUS_IS_OK(ret) ) {
- DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid));
- *uid = id.uid;
- }
-
- return ret;
-
-}
-
-/*****************************************************************
- *THE CANONICAL* convert SID to gid function.
- if it is a foreign sid or it is in idmap rid range check idmap,
- otherwise falls back to the legacy algorithmic mapping.
- Group mapping is used for gids that maps to Wellknown SIDs
- Returns True if this name is a user sid and the conversion
- was done correctly, False if not.
-*****************************************************************/
-
-NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- unid_t id;
-
- DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
-
- flags |= ID_GROUPID;
-
- ret = idmap_get_id_from_sid(&id, (int *)&flags, sid);
-
- if ( NT_STATUS_IS_OK(ret) )
- {
- DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid));
- *gid = id.gid;
- }
-
- return ret;
-}
diff --git a/source/sam/nss_info.c b/source/sam/nss_info.c
deleted file mode 100644
index 6d01916754e..00000000000
--- a/source/sam/nss_info.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- nss info helpers
- Copyright (C) Guenther Deschner 2006
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_IDMAP
-
-static enum wb_posix_mapping wb_posix_map_type(const char *map_str)
-{
- if (strequal(map_str, "template"))
- return WB_POSIX_MAP_TEMPLATE;
- else if (strequal(map_str, "sfu"))
- return WB_POSIX_MAP_SFU;
- else if (strequal(map_str, "rfc2307"))
- return WB_POSIX_MAP_RFC2307;
- else if (strequal(map_str, "unixinfo"))
- return WB_POSIX_MAP_UNIXINFO;
-
- return WB_POSIX_MAP_UNKNOWN;
-}
-
-/* winbind nss info = rfc2307 SO36:sfu FHAIN:rfc2307 PANKOW:template
- *
- * syntax is:
- * 1st param: default setting
- * following ":" separated list elements:
- * DOMAIN:setting
- * setting can be one of "sfu", "rfc2307", "template", "unixinfo"
- */
-
-enum wb_posix_mapping get_nss_info(const char *domain_name)
-{
- const char **list = lp_winbind_nss_info();
- enum wb_posix_mapping map_templ = WB_POSIX_MAP_TEMPLATE;
- int i;
-
- DEBUG(11,("get_nss_info for %s\n", domain_name));
-
- if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) {
- return WB_POSIX_MAP_TEMPLATE;
- }
-
- if ((map_templ = wb_posix_map_type(list[0])) == WB_POSIX_MAP_UNKNOWN) {
- DEBUG(0,("get_nss_info: invalid setting: %s\n", list[0]));
- return WB_POSIX_MAP_TEMPLATE;
- }
-
- DEBUG(11,("get_nss_info: using \"%s\" by default\n", list[0]));
-
- for (i=0; list[i]; i++) {
-
- const char *p = list[i];
- fstring tok;
-
- if (!next_token(&p, tok, ":", sizeof(tok))) {
- DEBUG(0,("get_nss_info: no \":\" delimitier found\n"));
- continue;
- }
-
- if (strequal(tok, domain_name)) {
-
- enum wb_posix_mapping type;
-
- if ((type = wb_posix_map_type(p)) == WB_POSIX_MAP_UNKNOWN) {
- DEBUG(0,("get_nss_info: invalid setting: %s\n", p));
- /* return WB_POSIX_MAP_TEMPLATE; */
- continue;
- }
-
- DEBUG(11,("get_nss_info: using \"%s\" for domain: %s\n", p, tok));
-
- return type;
- }
- }
-
- return map_templ;
-}
-
-const char *wb_posix_map_str(enum wb_posix_mapping mtype)
-{
- switch (mtype) {
- case WB_POSIX_MAP_TEMPLATE:
- return "template";
- case WB_POSIX_MAP_SFU:
- return "sfu";
- case WB_POSIX_MAP_RFC2307:
- return "rfc2307";
- case WB_POSIX_MAP_UNIXINFO:
- return "unixinfo";
- default:
- break;
- }
- return NULL;
-}
diff --git a/source/script/installman.sh b/source/script/installman.sh
index 869ce6ee38e..7edc707ab07 100755
--- a/source/script/installman.sh
+++ b/source/script/installman.sh
@@ -49,6 +49,7 @@ for lang in $langs; do
# Check if this man page if required by the configured feature set
case "${MP_BASENAME}" in
smbsh.1) test -z "${SMBWRAPPER}" && continue ;;
+ smbmnt.8|smbmount.8|smbumount.8) test -z "${SMBMOUNT_PROGS}" && continue ;;
*) ;;
esac
diff --git a/source/script/installswat.sh b/source/script/installswat.sh
index f4220b3c632..567bfa1a016 100755
--- a/source/script/installswat.sh
+++ b/source/script/installswat.sh
@@ -77,11 +77,15 @@ for ln in $LANGS; do
echo $FNAME
if test "$mode" = 'install'; then
if [ "x$BOOKDIR" = "x" ]; then
- cat $f | sed 's/@BOOKDIR@.*$//' > $f.tmp
+ cat $f | sed 's/@BOOKDIR@.*$//' > $FNAME.tmp
else
- cat $f | sed 's/@BOOKDIR@//' > $f.tmp
+ cat $f | sed 's/@BOOKDIR@//' > $FNAME.tmp
fi
- f=$f.tmp
+ if test ! -f "$FNAME.tmp"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ f=$FNAME.tmp
cp "$f" "$FNAME"
rm -f "$f"
if test ! -f "$FNAME"; then
diff --git a/source/script/mkbuildoptions.awk b/source/script/mkbuildoptions.awk
index 1e7b74b8d9c..20b20384a26 100644
--- a/source/script/mkbuildoptions.awk
+++ b/source/script/mkbuildoptions.awk
@@ -25,6 +25,7 @@ BEGIN {
print "#include \"dynconfig.h\"";
print "";
print "static void output(BOOL screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3);";
+ print "void build_options(BOOL screen);";
print "";
print "";
print "/****************************************************************************";
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index a0f3096c842..65a10c856e0 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -48,6 +48,16 @@ END {
printf "BOOL %s(int );\n", a[2]
}
+/^FN_LOCAL_PARM_BOOL/ {
+ split($0,a,"[,()]")
+ printf "BOOL %s(const struct share_params *p );\n", a[2]
+}
+
+/^FN_LOCAL_PARM_INTEGER/ {
+ split($0,a,"[,()]")
+ printf "int %s(const struct share_params *p );\n", a[2]
+}
+
/^FN_LOCAL_LIST/ {
split($0,a,"[,()]")
printf "const char **%s(int );\n", a[2]
@@ -58,6 +68,11 @@ END {
printf "char *%s(int );\n", a[2]
}
+/^FN_LOCAL_PARM_STRING/ {
+ split($0,a,"[,()]")
+ printf "char *%s(const struct share_params *p );\n", a[2]
+}
+
/^FN_LOCAL_CONST_STRING/ {
split($0,a,"[,()]")
printf "const char *%s(int );\n", a[2]
@@ -70,7 +85,7 @@ END {
/^FN_LOCAL_CHAR/ {
split($0,a,"[,()]")
- printf "char %s(int );\n", a[2]
+ printf "char %s(const struct share_params *p );\n", a[2]
}
/^FN_GLOBAL_BOOL/ {
@@ -136,7 +151,7 @@ END {
gotstart = 1;
}
- if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR|ELOG_TDB/ ) {
+ if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR|ELOG_TDB|codepoint_t/ ) {
gotstart = 1;
}
diff --git a/source/script/mkproto.sh b/source/script/mkproto.sh
index 62041c7e331..e46e73e3e90 100755
--- a/source/script/mkproto.sh
+++ b/source/script/mkproto.sh
@@ -25,7 +25,7 @@ header="$1"
shift
headertmp="$header.$$.tmp~"
-proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'ubiqx/|wrapped|modules/getdate'`"
+proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'tdb/|wrapped|modules/getdate'`"
echo creating $header
diff --git a/source/script/tests/gdb_backtrace b/source/script/tests/gdb_backtrace
index 2ea6a4d00a1..b19a5b2f4b7 100644
--- a/source/script/tests/gdb_backtrace
+++ b/source/script/tests/gdb_backtrace
@@ -1,41 +1,87 @@
-#! /bin/sh
-#
-# Author: Andrew Tridgell <tridge at samba dot org>
+#!/bin/sh
+
+BASENAME=`basename $0`
+
+if [ -n "$VALGRIND" -o -n "$SMBD_VALGRIND" ]; then
+ echo "${BASENAME}: Not running debugger under valgrind"
+ exit 1
+fi
# we want everything on stderr, so the program is not disturbed
exec 1>&2
-BASENAME=$( basename $0)
+BASENAME=`basename $0`
+UNAME=`uname`
+
+PID=$1
+BINARY=$2
-test -z ${GDB_BIN} && GDB_BIN=$( type -p gdb)
-if [ -z ${GDB_BIN} ]; then
- echo "ERROR: ${BASENAME} needs an installed gdb. "
+test x"${PID}" = x"" && {
+ echo "Usage: ${BASENAME} <pid> [<binary>]"
exit 1
-fi
+}
+
+DB_LIST="gdb"
+case "${UNAME}" in
+ #
+ # on Tru64 we need to try ladebug first
+ # because gdb crashes itself...
+ #
+ OSF1)
+ DB_LIST="ladebug ${DB_LIST}"
+ ;;
+esac
-if [ -z $1 ]; then
- echo "ERROR: ${BASENAME} needs a PID. "
+for DB in ${DB_LIST}; do
+ DB_BIN=`which ${DB} 2>/dev/null`
+ test x"${DB_BIN}" != x"" && {
+ break
+ }
+done
+
+test x"${DB_BIN}" = x"" && {
+ echo "${BASENAME}: ERROR: No debugger found."
exit 1
-fi
-PID=$1
+}
-# use /dev/shm as default temp directory
-test -d /dev/shm && \
- TMP_BASE_DIR=/dev/shm || \
- TMP_BASE_DIR=/var/tmp
-TMPFILE=$( mktemp -p ${TMP_BASE_DIR} backtrace.XXXXXX)
-if [ $? -ne 0 ]; then
- echo "ERROR: ${basename} can't create temp file in ${TMP_BASE_DIR}. "
+#
+# we first try to use /proc/${PID}/exe
+# then fallback to the binary from the commandline
+# then we search for the commandline argument with
+# 'which'
+#
+test -f "/proc/${PID}/exe" && BINARY="/proc/${PID}/exe"
+test x"${BINARY}" = x"" && BINARY="/proc/${PID}/exe"
+test -f "${BINARY}" || BINARY=`which ${BINARY}`
+
+test -f "${BINARY}" || {
+ echo "${BASENAME}: ERROR: Cannot find binary '${BINARY}'."
exit 1
-fi
+}
+
+echo "${BASENAME}: Trying to use ${DB_BIN} on ${BINARY} on PID ${PID}"
-cat << EOF > "${TMPFILE}"
-set height 0
-up 8
+BATCHFILE_PRE=/tmp/gdb_backtrace_pre.$$
+BATCHFILE_MAIN=/tmp/gdb_backtrace_main.$$
+case "${DB}" in
+ ladebug)
+cat << EOF > ${BATCHFILE_PRE}
+set \$stoponattach
+EOF
+
+cat << EOF > ${BATCHFILE_MAIN}
+where
+quit
+EOF
+ ${DB_BIN} -c "${BATCHFILE_MAIN}" -i "${BATCHFILE_PRE}" -pid "${PID}" "${BINARY}"
+ ;;
+ gdb)
+cat << EOF > ${BATCHFILE_MAIN}
+set height 1000
bt full
quit
EOF
-
-${GDB_BIN} -x "${TMPFILE}" "/proc/${PID}/exe" "${PID}"
-
-/bin/rm -f "${TMPFILE}"
+ ${DB_BIN} -x "${BATCHFILE_MAIN}" "${BINARY}" "${PID}"
+ ;;
+esac
+/bin/rm -f ${BATCHFILE_PRE} ${BATCHFILE_MAIN}
diff --git a/source/script/tests/selftest.sh b/source/script/tests/selftest.sh
index fe943b87b5e..9a1f70c440a 100755
--- a/source/script/tests/selftest.sh
+++ b/source/script/tests/selftest.sh
@@ -32,12 +32,14 @@ SERVER_IP=127.0.0.2
USERNAME=`PATH=/usr/ucb:$PATH whoami`
PASSWORD=test
-SRCDIR=`pwd`
+SRCDIR="`dirname $0`/../.."
+BINDIR="`pwd`/bin"
SCRIPTDIR=$SRCDIR/script/tests
SHRDIR=$PREFIX_ABS/tmp
LIBDIR=$PREFIX_ABS/lib
PIDDIR=$PREFIX_ABS/pid
CONFFILE=$LIBDIR/client.conf
+SAMBA4CONFFILE=$LIBDIR/samba4client.conf
SERVERCONFFILE=$LIBDIR/server.conf
COMMONCONFFILE=$LIBDIR/common.conf
PRIVATEDIR=$PREFIX_ABS/private
@@ -45,10 +47,13 @@ LOCKDIR=$PREFIX_ABS/lockdir
LOGDIR=$PREFIX_ABS/logs
SOCKET_WRAPPER_DIR=$PREFIX/sw
CONFIGURATION="-s $CONFFILE"
+SAMBA4CONFIGURATION="-s $SAMBA4CONFFILE"
-export PREFIX PREFIX_ABS CONFIGURATION CONFFILE PATH SOCKET_WRAPPER_DIR DOMAIN
+export PREFIX PREFIX_ABS
+export CONFIGURATION CONFFILE SAMBA4CONFIGURATION SAMBA4CONFFILE
+export PATH SOCKET_WRAPPER_DIR DOMAIN
export PRIVATEDIR LIBDIR PIDDIR LOCKDIR LOGDIR SERVERCONFFILE
-export SRCDIR SCRIPTDIR
+export SRCDIR SCRIPTDIR BINDIR
export USERNAME PASSWORD
export SMBTORTURE4
export SERVER SERVER_IP
@@ -93,14 +98,23 @@ cat >$COMMONCONFFILE<<EOF
passdb backend = tdbsam
name resolve order = bcast
-
- panic action = $SCRIPTDIR/gdb_backtrace %d
EOF
+TORTURE_INTERFACES='127.0.0.6/8,127.0.0.7/8,127.0.0.8/8,127.0.0.9/8,127.0.0.10/8,127.0.0.11/8'
+
cat >$CONFFILE<<EOF
[global]
- netbios name = TORTURE26
- interfaces = 127.0.0.26/8
+ netbios name = TORTURE_6
+ interfaces = $TORTURE_INTERFACES
+ panic action = $SCRIPTDIR/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
+ include = $COMMONCONFFILE
+EOF
+
+cat >$SAMBA4CONFFILE<<EOF
+[global]
+ netbios name = TORTURE_6
+ interfaces = $TORTURE_INTERFACES
+ panic action = $SCRIPTDIR/gdb_backtrace %PID% %PROG%
include = $COMMONCONFFILE
EOF
@@ -109,17 +123,44 @@ cat >$SERVERCONFFILE<<EOF
netbios name = $SERVER
interfaces = $SERVER_IP/8
bind interfaces only = yes
+ panic action = $SCRIPTDIR/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
include = $COMMONCONFFILE
+ ; Necessary to add the build farm hacks
+ add user script = /bin/false
+ add machine script = /bin/false
+
kernel oplocks = no
+ syslog = no
+ printing = bsd
+ printcap name = /dev/null
+
[tmp]
path = $PREFIX_ABS/tmp
read only = no
smbd:sharedelay = 100000
+ map hidden = yes
+ map system = yes
+ create mask = 755
+[hideunread]
+ copy = tmp
+ hide unreadable = yes
+[hideunwrite]
+ copy = tmp
+ hide unwriteable files = yes
+[print1]
+ copy = tmp
+ printable = yes
+ printing = test
+[print2]
+ copy = print1
+[print3]
+ copy = print1
+[print4]
+ copy = print1
EOF
-
##
## create a test account
##
@@ -129,10 +170,6 @@ EOF
echo "DONE";
-if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
- CONFIGURATION="$CONFIGURATION --option=\"torture:progress=no\""
-fi
-
SERVER_TEST_FIFO="$PREFIX/server_test.fifo"
export SERVER_TEST_FIFO
NMBD_TEST_LOG="$PREFIX/nmbd_test.log"
@@ -140,6 +177,9 @@ export NMBD_TEST_LOG
SMBD_TEST_LOG="$PREFIX/smbd_test.log"
export SMBD_TEST_LOG
+MAKE_TEST_BINARY=""
+export MAKE_TEST_BINARY
+
# start off with 0 failures
failed=0
export failed
@@ -151,18 +191,18 @@ export SOCKET_WRAPPER_DEFAULT_IFACE
samba3_check_or_start
# ensure any one smbtorture call doesn't run too long
-# and smbtorture will use 127.0.0.26 as source address by default
-SOCKET_WRAPPER_DEFAULT_IFACE=26
+# and smbtorture will use 127.0.0.6 as source address by default
+SOCKET_WRAPPER_DEFAULT_IFACE=6
export SOCKET_WRAPPER_DEFAULT_IFACE
-TORTURE4_INTERFACES='127.0.0.26/8,127.0.0.27/8,127.0.0.28/8,127.0.0.29/8,127.0.0.30/8,127.0.0.31/8'
-TORTURE4_OPTIONS="--maximum-runtime=$TORTURE_MAXTIME --option=interfaces=$TORTURE4_INTERFACES $CONFIGURATION"
+TORTURE4_OPTIONS="$SAMBA4CONFIGURATION"
+TORTURE4_OPTIONS="$TORTURE4_OPTIONS --maximum-runtime=$TORTURE_MAXTIME"
+TORTURE4_OPTIONS="$TORTURE4_OPTIONS --target=samba3"
export TORTURE4_OPTIONS
if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=torture:progress=no"
fi
-TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=target:samba3=yes"
##
## ready to go...now loop through the tests
@@ -181,8 +221,8 @@ START=`date`
bin/nmblookup $CONFIGURATION $SERVER
# make sure smbd is also up set
echo "wait for smbd"
- bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2
- bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 | head -2
+ bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2
+ bin/smbclient $CONFIGURATION -L $SERVER_IP -U% -p 139 | head -2
failed=0
diff --git a/source/script/tests/test_functions.sh b/source/script/tests/test_functions.sh
index 368832a506d..1cc9ea12643 100644
--- a/source/script/tests/test_functions.sh
+++ b/source/script/tests/test_functions.sh
@@ -43,8 +43,11 @@ samba3_check_or_start() {
if test x"$NMBD_MAXTIME" = x; then
NMBD_MAXTIME=2700
fi
- timelimit $NMBD_MAXTIME $NMBD_VALGRIND $SRCDIR/bin/nmbd -F -S --no-process-group -d0 -s $SERVERCONFFILE > $NMBD_TEST_LOG 2>&1 &
+ MAKE_TEST_BINARY=$BINDIR/nmbd
+ export MAKE_TEST_BINARY
+ timelimit $NMBD_MAXTIME $NMBD_VALGRIND $BINDIR/nmbd -F -S --no-process-group -d0 -s $SERVERCONFFILE > $NMBD_TEST_LOG 2>&1 &
TIMELIMIT_NMBD_PID=$!
+ MAKE_TEST_BINARY=
echo $TIMELIMIT_NMBD_PID > $PIDDIR/timelimit.nmbd.pid
wait $TIMELIMIT_NMBD_PID
ret=$?;
@@ -72,8 +75,11 @@ samba3_check_or_start() {
if test x"$SMBD_MAXTIME" = x; then
SMBD_MAXTIME=2700
fi
- timelimit $SMBD_MAXTIME $SMBD_VALGRIND $SRCDIR/bin/smbd -F -S --no-process-group -d0 -s $SERVERCONFFILE > $SMBD_TEST_LOG 2>&1 &
+ MAKE_TEST_BINARY=$BINDIR/smbd
+ export MAKE_TEST_BINARY
+ timelimit $SMBD_MAXTIME $SMBD_VALGRIND $BINDIR/smbd -F -S --no-process-group -d0 -s $SERVERCONFFILE > $SMBD_TEST_LOG 2>&1 &
TIMELIMIT_SMBD_PID=$!
+ MAKE_TEST_BINARY=
echo $TIMELIMIT_SMBD_PID > $PIDDIR/timelimit.smbd.pid
wait $TIMELIMIT_SMBD_PID
ret=$?;
@@ -133,11 +139,26 @@ testit() {
fi
name=$1
shift 1
- SERVERS_ARE_UP="no"
- TEST_LOG="$PREFIX/test_log.$$"
- trap "rm -f $TEST_LOG" EXIT
+ binary=$1
cmdline="$*"
+ SERVERS_ARE_UP="no"
+
+ shname=`echo $name | \
+ sed -e 's%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g'`
+
+ UNIQUE_PID=`/bin/sh -c 'echo $$'`
+ TEST_LOG="$PREFIX/test_log.${UNIQUE_PID}"
+ TEST_PCAP="$PREFIX/test_${shname}_${UNIQUE_PID}.pcap"
+ trap "rm -f $TEST_LOG $TEST_PCAP" EXIT
+
+ if [ -z "$nmbd_log_size" ]; then
+ nmbd_log_size=`wc -l < $NMBD_TEST_LOG`;
+ fi
+ if [ -z "$smbd_log_size" ]; then
+ smbd_log_size=`wc -l < $SMBD_TEST_LOG`;
+ fi
+
if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
echo "--==--==--==--==--==--==--==--==--==--==--"
echo "Running test $name (level 0 stdout)"
@@ -160,17 +181,44 @@ testit() {
fi
return 1
fi
-
+
+ if [ x"$MAKE_TEST_ENABLE_PCAP" = x"yes" ];then
+ SOCKET_WRAPPER_PCAP_FILE=$TEST_PCAP
+ export SOCKET_WRAPPER_PCAP_FILE
+ fi
+
+ MAKE_TEST_BINARY=$binary
+ export MAKE_TEST_BINARY
( $cmdline > $TEST_LOG 2>&1 )
status=$?
+ MAKE_TEST_BINARY=
+ # show any additional output from smbd that has happened in this test
+ samba3_nmbd_test_log && {
+ new_log_size=`wc -l < $NMBD_TEST_LOG`;
+ test "$new_log_size" = "$nmbd_log_size" || {
+ echo "NMBD OUTPUT:";
+ incr_log_size=`expr $new_log_size - $nmbd_log_size`;
+ tail -$incr_log_size $NMBD_TEST_LOG;
+ nmbd_log_size=$new_log_size;
+ }
+ }
+ samba3_smbd_test_log && {
+ new_log_size=`wc -l < $SMBD_TEST_LOG`;
+ test "$new_log_size" = "$smbd_log_size" || {
+ echo "SMBD OUTPUT:";
+ incr_log_size=`expr $new_log_size - $smbd_log_size`;
+ tail -$incr_log_size $SMBD_TEST_LOG;
+ smbd_log_size=$new_log_size;
+ }
+ }
+
if [ x"$status" != x"0" ]; then
echo "TEST OUTPUT:"
cat $TEST_LOG;
- samba3_nmbd_test_log && echo "NMBD OUTPUT:";
- samba3_nmbd_test_log && cat $NMBD_TEST_LOG;
- samba3_smbd_test_log && echo "SMBD OUTPUT:";
- samba3_smbd_test_log && cat $SMBD_TEST_LOG;
rm -f $TEST_LOG;
+ if [ x"$MAKE_TEST_ENABLE_PCAP" = x"yes" ];then
+ echo "TEST PCAP: $TEST_PCAP"
+ fi
if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
echo "=========================================="
echo "TEST FAILED: $name (status $status)"
@@ -178,15 +226,22 @@ testit() {
else
echo "TEST FAILED: $cmdline (status $status)"
fi
+ trap "" EXIT
return 1;
fi
rm -f $TEST_LOG;
+ if [ x"$MAKE_TEST_KEEP_PCAP" = x"yes" ];then
+ echo "TEST PCAP: $TEST_PCAP"
+ else
+ rm -f $TEST_PCAP;
+ fi
if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
echo "ALL OK: $cmdline"
echo "=========================================="
echo "TEST PASSED: $name"
echo "=========================================="
fi
+ trap "" EXIT
return 0;
}
diff --git a/source/script/tests/test_groupmap.sh b/source/script/tests/test_groupmap.sh
new file mode 100755
index 00000000000..46640a91312
--- /dev/null
+++ b/source/script/tests/test_groupmap.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+# test groupmap code tridge@samba.org September 2006
+# note that this needs root access to add unix groups,
+# so this cannot be run on the build farm
+
+testone() {
+ echo $*
+ $VALGRIND bin/net groupmap $*
+}
+
+tstart() {
+ TBASE=`date '+%s'`
+}
+
+treport() {
+ TNOW=`date '+%s'`
+ echo "Took `expr $TNOW - $TBASE` seconds"
+ TBASE=$TNOW
+}
+
+rm -f $PREFIX_ABS/var/locks/group_mapping.?db
+
+NLOCAL=12
+NGROUP=11
+NBUILTIN=10
+DOMSID=`bin/net getlocalsid | awk '{print $6}'`
+FORSID="S-1-2-3-4-5"
+
+echo "DOMSID $DOMSID"
+echo "FORSID $FORSID"
+
+tstart
+echo "Creating unix groups"
+for i in `seq 1 1 $NLOCAL`; do
+ unixgroup=testlocal$i;
+ gid=`expr 30000 + $i`;
+ groupdel $unixgroup 2> /dev/null
+ groupadd -g $gid $unixgroup || exit 1
+done
+for i in `seq 1 1 $NGROUP`; do
+ unixgroup=testgrp$i;
+ gid=`expr 40000 + $i`;
+ groupdel $unixgroup 2> /dev/null
+ groupadd -g $gid $unixgroup || exit 1
+done
+for i in `seq 1 1 $NBUILTIN`; do
+ unixgroup=testb$i;
+ gid=`expr 50000 + $i`;
+ groupdel $unixgroup 2> /dev/null
+ groupadd -g $gid $unixgroup || exit 1
+done
+date
+
+treport
+
+echo "Creating local groups"
+for i in `seq 1 1 $NLOCAL`; do
+ unixgroup=testlocal$i;
+ ntgroup=ntlgrp$i;
+ rid=`expr 10000 + $i`;
+ testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=local || exit 1
+done
+
+echo "trying a duplicate add"
+testone add rid=10001 unixgroup=testlocal1 ntgroup=foo type=local && exit 1
+
+treport
+
+echo "Creating domain groups"
+for i in `seq 1 1 $NGROUP`; do
+ unixgroup=testgrp$i;
+ ntgroup=ntgrp$i;
+ rid=`expr 20000 + $i`;
+ testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=domain || exit 1
+done
+
+treport
+
+echo "Creating builtin groups"
+for i in `seq 1 1 $NBUILTIN`; do
+ unixgroup=testb$i;
+ ntgroup=ntbgrp$i;
+ rid=`expr 30000 + $i`;
+ testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=builtin || exit 1
+done
+
+treport
+
+echo "Adding domain groups to local groups"
+for i in `seq 1 1 $NLOCAL`; do
+ for j in `seq 1 1 $i`; do
+
+ lrid=`expr 10000 + $i`;
+ drid=`expr 20000 + $j`;
+
+ testone addmem $DOMSID-$lrid $DOMSID-$drid || exit 1
+ ( testone listmem $DOMSID-$lrid | sort -r ) || exit 1
+ done
+done
+
+echo "trying a duplicate addmem"
+testone addmem $DOMSID-10001 $DOMSID-20001 && exit 1
+
+echo "Adding foreign SIDs to local groups"
+for i in `seq 1 1 $NLOCAL`; do
+ for j in `seq 1 1 $i`; do
+
+ lrid=`expr 10000 + $i`;
+ frid=`expr 70000 + $j`;
+
+ testone addmem $DOMSID-$lrid $FORSID-$frid || exit 1
+ ( testone listmem $DOMSID-$lrid | sort -r ) || exit 1
+ done
+done
+
+echo "trying a duplicate foreign addmem"
+testone addmem $DOMSID-10001 $FORSID-70001 && exit 1
+
+treport
+
+echo "Listing local group memberships of domain groups"
+for i in `seq 1 1 $NGROUP`; do
+ rid=`expr 20000 + $i`;
+ ( testone memberships $DOMSID-$rid | sort -r ) || exit 1
+done
+
+echo "Trying memberships on bogus sid"
+testone memberships $DOMSID-999999 || exit 1
+
+treport
+
+testone list | sort
+
+echo "Deleting some domain groups"
+for i in `seq 2 2 $NGROUP`; do
+ drid=`expr 20000 + $i`;
+ testone delete sid=$DOMSID-$drid || exit 1
+done
+
+echo "Trying duplicate domain group delete"
+testone delete sid=$DOMSID-20002 && exit 1
+
+treport
+
+echo "Deleting some local groups"
+for i in `seq 2 4 $NLOCAL`; do
+ lrid=`expr 10000 + $i`;
+ testone delete sid=$DOMSID-$lrid || exit 1
+done
+
+echo "Trying duplicate local group delete"
+testone delete sid=$DOMSID-10002 && exit 1
+
+treport
+
+echo "Modifying some domain groups"
+for i in `seq 3 2 $NGROUP`; do
+ drid=`expr 20000 + $i`;
+ testone modify sid=$DOMSID-$drid comment="newcomment-$i" type=domain || exit 1
+done
+
+treport
+
+testone list | sort
+
+echo "Listing local group memberships"
+for i in `seq 1 1 $NLOCAL`; do
+ rid=`expr 20000 + $i`;
+ ( testone memberships $DOMSID-$rid | sort -r ) || exit 1
+done
+
+treport
+
+echo "Removing some domain groups from local groups"
+for i in `seq 1 2 $NLOCAL`; do
+ for j in `seq 1 3 $i`; do
+
+ lrid=`expr 10000 + $i`;
+ drid=`expr 20000 + $j`;
+
+ testone delmem $DOMSID-$lrid $DOMSID-$drid || exit 1
+ done
+done
+
+echo "Trying duplicate delmem"
+testone delmem $DOMSID-10001 $DOMSID-20001 && exit 1
+
+treport
+
+echo "Listing local group memberships"
+for i in `seq 1 1 $NLOCAL`; do
+ rid=`expr 20000 + $i`;
+ ( testone memberships $DOMSID-$rid | sort -r ) || exit 1
+done
+
+treport
+
+echo "Deleting unix groups"
+for i in `seq 1 1 $NLOCAL`; do
+ unixgroup=testlocal$i;
+ groupdel $unixgroup 2> /dev/null
+done
+for i in `seq 1 1 $NGROUP`; do
+ unixgroup=testgrp$i;
+ groupdel $unixgroup 2> /dev/null
+done
+for i in `seq 1 1 $NBUILTIN`; do
+ unixgroup=testb$i;
+ groupdel $unixgroup 2> /dev/null
+done
+
+treport
+
+echo "ALL DONE"
diff --git a/source/script/tests/test_local_s3.sh b/source/script/tests/test_local_s3.sh
new file mode 100755
index 00000000000..019a51559be
--- /dev/null
+++ b/source/script/tests/test_local_s3.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# this runs the file serving tests that are expected to pass with samba3
+
+if [ $# != 0 ]; then
+cat <<EOF
+Usage: test_local_s3.sh
+EOF
+exit 1;
+fi
+
+incdir=`dirname $0`
+. $incdir/test_functions.sh
+
+failed=0
+
+testit "talloctort" $VALGRIND $BINDIR/talloctort || \
+ failed=`expr $failed + 1`
+
+testit "replacetort" $VALGRIND $BINDIR/replacetort || \
+ failed=`expr $failed + 1`
+
+testok $0 $failed
diff --git a/source/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh
index 2274a1f7fe5..690399f8212 100755
--- a/source/script/tests/test_posix_s3.sh
+++ b/source/script/tests/test_posix_s3.sh
@@ -21,26 +21,32 @@ incdir=`dirname $0`
base="BASE-ATTR BASE-CHARSET BASE-CHKPATH BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE"
base="$base BASE-DENY1 BASE-DENY2 BASE-DENY3 BASE-DENYDOS BASE-DIR1 BASE-DIR2"
-base="$base BASE-DISCONNECT BASE-FDPASS BASE-LOCK1 BASE-LOCK2 BASE-LOCK3 BASE-LOCK4"
-base="$base BASE-LOCK5 BASE-LOCK6 BASE-LOCK7 BASE-MANGLE BASE-NEGNOWAIT BASE-NTDENY1"
+base="$base BASE-DISCONNECT BASE-FDPASS BASE-LOCK"
+base="$base BASE-MANGLE BASE-NEGNOWAIT BASE-NTDENY1"
base="$base BASE-NTDENY2 BASE-OPEN BASE-OPENATTR BASE-PROPERTIES BASE-RENAME BASE-RW1"
base="$base BASE-SECLEAK BASE-TCON BASE-TCONDEV BASE-TRANS2 BASE-UNLINK BASE-VUID"
-base="$base BASE-XCOPY"
+base="$base BASE-XCOPY BASE-SAMBA3ERROR"
raw="RAW-ACLS RAW-CHKPATH RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
raw="$raw RAW-IOCTL RAW-LOCK RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN RAW-OPLOCK"
raw="$raw RAW-QFILEINFO RAW-QFSINFO RAW-READ RAW-RENAME RAW-SEARCH RAW-SEEK"
raw="$raw RAW-SFILEINFO RAW-SFILEINFO-BUG RAW-STREAMS RAW-UNLINK RAW-WRITE"
+raw="$raw RAW-SAMBA3HIDE RAW-SAMBA3BADPATH"
-rpc="RPC-AUTHCONTEXT"
+rpc="RPC-AUTHCONTEXT RPC-BINDSAMBA3 RPC-SAMBA3-SRVSVC RPC-SAMBA3-SHARESEC"
+rpc="$rpc RPC-UNIXINFO RPC-SAMBA3-SPOOLSS RPC-SAMBA3-WKSSVC"
+
+if test x$RUN_FROM_BUILD_FARM = xyes; then
+ rpc="$rpc RPC-NETLOGSAMBA3 RPC-SAMBA3SESSIONKEY RPC-SAMBA3-GETUSERNAME"
+fi
tests="$base $raw $rpc"
-skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-OPENATTR BASE-TCONDEV"
-skipped="$skipped RAW-ACLS RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
+skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-OPENATTR BASE-TCONDEV"
+skipped="$skipped RAW-ACLS RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
skipped="$skipped RAW-IOCTL RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN"
skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-RENAME RAW-SEARCH"
-skipped="$skipped RAW-SFILEINFO RAW-STREAMS RAW-UNLINK RAW-WRITE"
+skipped="$skipped RAW-SFILEINFO RAW-STREAMS RAW-WRITE"
echo "WARNING: Skipping tests $skipped"
diff --git a/source/script/tests/test_smbclient_s3.sh b/source/script/tests/test_smbclient_s3.sh
index d95657467d7..3a8f3bd5b6c 100755
--- a/source/script/tests/test_smbclient_s3.sh
+++ b/source/script/tests/test_smbclient_s3.sh
@@ -11,7 +11,7 @@ fi
SERVER="$1"
SERVER_IP="$2"
-SMBCLIENT="$VALGRIND ${SMBCLIENT:-$SRCDIR/bin/smbclient} $CONFIGURATION"
+SMBCLIENT="$VALGRIND ${SMBCLIENT:-$BINDIR/smbclient} $CONFIGURATION"
incdir=`dirname $0`
. $incdir/test_functions.sh
@@ -24,7 +24,7 @@ test_noninteractive_no_prompt()
prompt="smb"
echo du | \
- $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp 2>&1 | \
+ $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp 2>&1 | \
grep $prompt
if [ $? = 0 ] ; then
@@ -48,7 +48,7 @@ quit
EOF
CLI_FORCE_INTERACTIVE=yes \
- $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp \
+ $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp \
< $tmpfile 2>/dev/null | \
grep $prompt
@@ -63,8 +63,8 @@ EOF
fi
}
-testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
-testit "smbclient -L $SERVER" $SMBCLIENT -L $SERVER -N -p 139 || failed=`expr $failed + 1`
+testit "smbclient -L $SERVER_IP" $SMBCLIENT $CONFIGURATION -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
+testit "smbclient -L $SERVER" $SMBCLIENT $CONFIGURATION -L $SERVER -N -p 139 || failed=`expr $failed + 1`
testit "noninteractive smbclient does not prompt" \
test_noninteractive_no_prompt || \
diff --git a/source/script/tests/test_smbtorture_s3.sh b/source/script/tests/test_smbtorture_s3.sh
index d0e15345df8..38ab40f09d7 100755
--- a/source/script/tests/test_smbtorture_s3.sh
+++ b/source/script/tests/test_smbtorture_s3.sh
@@ -24,11 +24,11 @@ tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE "
tests="$tests OPLOCK1 OPLOCK2 OPLOCK3"
tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3"
tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K"
-tests="$tests PIPE_NUMBER TCON2 IOCTL CHKPATH FDSESS"
+tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE"
skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN"
skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST"
-skipped3="MANGLE UTABLE"
+skipped3="MANGLE UTABLE PIPE_NUMBER"
echo "Skipping the following tests:"
echo "$skipped1"
echo "$skipped2"
@@ -41,7 +41,7 @@ for t in $tests; do
fi
start=""
name="$t"
- testit "$name" $VALGRIND $SRCDIR/bin/smbtorture $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
+ testit "$name" $VALGRIND $BINDIR/smbtorture $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
done
testok $0 $failed
diff --git a/source/script/tests/tests_all.sh b/source/script/tests/tests_all.sh
index 059f9d1a376..dd593899e4b 100755
--- a/source/script/tests/tests_all.sh
+++ b/source/script/tests/tests_all.sh
@@ -1,4 +1,5 @@
+$SCRIPTDIR/test_local_s3.sh || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP || failed=`expr $failed + $?`
diff --git a/source/services/svc_winreg.c b/source/services/svc_winreg.c
index 1bccee246e2..8fa49d3c3b4 100644
--- a/source/services/svc_winreg.c
+++ b/source/services/svc_winreg.c
@@ -46,6 +46,7 @@ static WERROR winreg_status( const char *service, SERVICE_STATUS *service_status
ZERO_STRUCTP( service_status );
service_status->type = 0x20;
+ service_status->controls_accepted = SVCCTL_ACCEPT_NONE;
service_status->state = SVCCTL_RUNNING;
return WERR_OK;
diff --git a/source/smbd/aio.c b/source/smbd/aio.c
index c71c3740433..8a9fabf2286 100644
--- a/source/smbd/aio.c
+++ b/source/smbd/aio.c
@@ -49,7 +49,8 @@ static struct aio_extra *aio_list_head;
of the aio_read call.
*****************************************************************************/
-static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid)
+static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen,
+ uint16 mid)
{
struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra);
@@ -77,7 +78,10 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, ui
of the aio_write call.
*****************************************************************************/
-static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen, uint16 mid)
+static struct aio_extra *create_aio_ex_write(files_struct *fsp,
+ size_t inbuflen,
+ size_t outbuflen,
+ uint16 mid)
{
struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra);
@@ -92,16 +96,13 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen
SAFE_FREE(aio_ex);
return NULL;
}
- /* Steal the input buffer containing the write data from the main SMB call. */
- /* We must re-allocate a new one here. */
- if (NewInBuffer(&aio_ex->inbuf) == NULL) {
+
+ if (!(aio_ex->inbuf = SMB_MALLOC_ARRAY(char, inbuflen))) {
SAFE_FREE(aio_ex->outbuf);
SAFE_FREE(aio_ex);
return NULL;
}
- /* aio_ex->inbuf now contains the stolen old InBuf containing the data to write. */
-
DLIST_ADD(aio_list_head, aio_ex);
aio_ex->fsp = fsp;
aio_ex->read_req = False;
@@ -116,9 +117,7 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen
static void delete_aio_ex(struct aio_extra *aio_ex)
{
DLIST_REMOVE(aio_list_head, aio_ex);
- /* Safe to do as we've removed ourselves from the in use list first. */
- free_InBuffer(aio_ex->inbuf);
-
+ SAFE_FREE(aio_ex->inbuf);
SAFE_FREE(aio_ex->outbuf);
SAFE_FREE(aio_ex);
}
@@ -154,7 +153,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE];
static void signal_handler(int sig, siginfo_t *info, void *unused)
{
- if (signals_received < AIO_PENDING_SIZE - 1) {
+ if (signals_received < AIO_PENDING_SIZE) {
aio_pending_array[signals_received] = info->si_value.sival_int;
signals_received++;
} /* Else signal is lost. */
@@ -214,13 +213,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
return False;
}
- /* Only do this on non-chained and non-chaining reads not using the write cache. */
- if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) {
+ /* Only do this on non-chained and non-chaining reads not using the
+ * write cache. */
+ if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF)
+ || (lp_write_cache_size(SNUM(conn)) != 0) ) {
return False;
}
if (outstanding_aio_calls >= AIO_PENDING_SIZE) {
- DEBUG(10,("schedule_aio_read_and_X: Already have %d aio activities outstanding.\n",
+ DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
+ "activities outstanding.\n",
outstanding_aio_calls ));
return False;
}
@@ -229,7 +231,8 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
checked smb_maxcnt is 128k or less. */
bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt;
- if ((aio_ex = create_aio_ex_read(fsp, bufsize, SVAL(inbuf,smb_mid))) == NULL) {
+ if ((aio_ex = create_aio_ex_read(fsp, bufsize,
+ SVAL(inbuf,smb_mid))) == NULL) {
DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
return False;
}
@@ -251,14 +254,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
a->aio_sigevent.sigev_value.sival_int = aio_ex->mid;
if (SMB_VFS_AIO_READ(fsp,a) == -1) {
- DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n",
- strerror(errno) ));
+ DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
+ "Error %s\n", strerror(errno) ));
delete_aio_ex(aio_ex);
return False;
}
- DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, offset %.0f, len = %u (mid = %u)\n",
- fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->mid ));
+ DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
+ "offset %.0f, len = %u (mid = %u)\n",
+ fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt,
+ (unsigned int)aio_ex->mid ));
srv_defer_sign_response(aio_ex->mid);
outstanding_aio_calls++;
@@ -278,40 +283,49 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
{
struct aio_extra *aio_ex;
SMB_STRUCT_AIOCB *a;
- size_t outbufsize;
+ size_t inbufsize, outbufsize;
BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
if (!min_aio_write_size || (numtowrite < min_aio_write_size)) {
/* Too small a write for aio request. */
- DEBUG(10,("schedule_aio_write_and_X: write size (%u) too small "
- "for minimum aio_write of %u\n",
+ DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
+ "small for minimum aio_write of %u\n",
(unsigned int)numtowrite,
(unsigned int)min_aio_write_size ));
return False;
}
- /* Only do this on non-chained and non-chaining reads not using the write cache. */
- if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) {
+ /* Only do this on non-chained and non-chaining reads not using the
+ * write cache. */
+ if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF)
+ || (lp_write_cache_size(SNUM(conn)) != 0) ) {
return False;
}
if (outstanding_aio_calls >= AIO_PENDING_SIZE) {
- DEBUG(3,("schedule_aio_write_and_X: Already have %d aio activities outstanding.\n",
+ DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
+ "activities outstanding.\n",
outstanding_aio_calls ));
- DEBUG(10,("schedule_aio_write_and_X: failed to schedule aio_write for file %s, offset %.0f, len = %u (mid = %u)\n",
- fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)SVAL(inbuf,smb_mid) ));
+ DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
+ "aio_write for file %s, offset %.0f, len = %u "
+ "(mid = %u)\n",
+ fsp->fsp_name, (double)startpos,
+ (unsigned int)numtowrite,
+ (unsigned int)SVAL(inbuf,smb_mid) ));
return False;
}
+ inbufsize = smb_len(inbuf) + 4;
outbufsize = smb_len(outbuf) + 4;
- if ((aio_ex = create_aio_ex_write(fsp, outbufsize, SVAL(inbuf,smb_mid))) == NULL) {
+ if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize,
+ SVAL(inbuf,smb_mid)))) {
DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
return False;
}
- /* Paranioa.... */
- SMB_ASSERT(aio_ex->inbuf == inbuf);
+ /* Copy the SMB header already setup in outbuf. */
+ memcpy(aio_ex->inbuf, inbuf, inbufsize);
/* Copy the SMB header already setup in outbuf. */
memcpy(aio_ex->outbuf, outbuf, outbufsize);
@@ -322,7 +336,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
/* Now set up the aio record for the write call. */
a->aio_fildes = fsp->fh->fd;
- a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */
+ a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, inbuf));
a->aio_nbytes = numtowrite;
a->aio_offset = startpos;
a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
@@ -330,33 +344,35 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
a->aio_sigevent.sigev_value.sival_int = aio_ex->mid;
if (SMB_VFS_AIO_WRITE(fsp,a) == -1) {
- DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n",
- strerror(errno) ));
- /* Replace global InBuf as we're going to do a normal write. */
- set_InBuffer(aio_ex->inbuf);
- aio_ex->inbuf = NULL;
+ DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
+ "Error %s\n", strerror(errno) ));
delete_aio_ex(aio_ex);
return False;
}
- if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) {
- /* Lie to the client and immediately claim we finished the write. */
+ if (!write_through && !lp_syncalways(SNUM(fsp->conn))
+ && fsp->aio_write_behind) {
+ /* Lie to the client and immediately claim we finished the
+ * write. */
SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
show_msg(aio_ex->outbuf);
if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) {
- exit_server("handle_aio_write: send_smb failed.");
+ exit_server_cleanly("handle_aio_write: send_smb "
+ "failed.");
}
- DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n",
- fsp->fsp_name ));
+ DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
+ "behind for file %s\n", fsp->fsp_name ));
} else {
srv_defer_sign_response(aio_ex->mid);
}
outstanding_aio_calls++;
- DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file %s, \
-offset %.0f, len = %u (mid = %u) outstanding_aio_calls = %d\n",
- fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->mid, outstanding_aio_calls ));
+ DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
+ "%s, offset %.0f, len = %u (mid = %u) "
+ "outstanding_aio_calls = %d\n",
+ fsp->fsp_name, (double)startpos, (unsigned int)numtowrite,
+ (unsigned int)aio_ex->mid, outstanding_aio_calls ));
return True;
}
@@ -381,14 +397,16 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
will return an error. Hopefully this is
true.... JRA. */
- /* If errno is ECANCELED then don't return anything to the client. */
+ /* If errno is ECANCELED then don't return anything to the
+ * client. */
if (errno == ECANCELED) {
srv_cancel_sign_response(aio_ex->mid);
return 0;
}
- DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. Error = %s\n",
- aio_ex->fsp->fsp_name, strerror(errno) ));
+ DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. "
+ "Error = %s\n",
+ aio_ex->fsp->fsp_name, strerror(errno) ));
outsize = (UNIXERROR(ERRDOS,ERRnoaccess));
ret = errno;
@@ -400,19 +418,23 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
SSVAL(smb_buf(outbuf),-2,nread);
- DEBUG( 3, ( "handle_aio_read_complete file %s max=%d nread=%d\n",
- aio_ex->fsp->fsp_name,
- aio_ex->acb.aio_nbytes, (int)nread ) );
+ DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
+ "nread=%d\n",
+ aio_ex->fsp->fsp_name,
+ aio_ex->acb.aio_nbytes, (int)nread ) );
}
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("handle_aio_read_complete: send_smb failed.");
+ exit_server_cleanly("handle_aio_read_complete: send_smb "
+ "failed.");
}
- DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n",
- aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)nread ));
+ DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
+ "for file %s, offset %.0f, len = %u\n",
+ aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset,
+ (unsigned int)nread ));
return ret;
}
@@ -433,17 +455,24 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
if (fsp->aio_write_behind) {
if (nwritten != numtowrite) {
if (nwritten == -1) {
- DEBUG(5,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! Error %s\n",
- fsp->fsp_name, strerror(errno) ));
+ DEBUG(5,("handle_aio_write_complete: "
+ "aio_write_behind failed ! File %s "
+ "is corrupt ! Error %s\n",
+ fsp->fsp_name, strerror(errno) ));
ret = errno;
} else {
- DEBUG(0,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! \
-Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (int)nwritten ));
+ DEBUG(0,("handle_aio_write_complete: "
+ "aio_write_behind failed ! File %s "
+ "is corrupt ! Wanted %u bytes but "
+ "only wrote %d\n", fsp->fsp_name,
+ (unsigned int)numtowrite,
+ (int)nwritten ));
ret = EIO;
}
} else {
- DEBUG(10,("handle_aio_write_complete: aio_write_behind completed for file %s\n",
- fsp->fsp_name ));
+ DEBUG(10,("handle_aio_write_complete: "
+ "aio_write_behind completed for file %s\n",
+ fsp->fsp_name ));
}
return 0;
}
@@ -452,11 +481,13 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (
fixed size length when we set up the aio call. */
if(nwritten == -1) {
- DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. nwritten == %d. Error = %s\n",
- fsp->fsp_name, (unsigned int)numtowrite,
- (int)nwritten, strerror(errno) ));
+ DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
+ "nwritten == %d. Error = %s\n",
+ fsp->fsp_name, (unsigned int)numtowrite,
+ (int)nwritten, strerror(errno) ));
- /* If errno is ECANCELED then don't return anything to the client. */
+ /* If errno is ECANCELED then don't return anything to the
+ * client. */
if (errno == ECANCELED) {
srv_cancel_sign_response(aio_ex->mid);
return 0;
@@ -473,25 +504,28 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (
SCVAL(outbuf,smb_rcls,ERRHRD);
SSVAL(outbuf,smb_err,ERRdiskfull);
}
-
- DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
+
+ DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
+ fsp->fnum, (int)numtowrite, (int)nwritten));
sync_file(fsp->conn,fsp, write_through);
}
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("handle_aio_write: send_smb failed.");
+ exit_server_cleanly("handle_aio_write: send_smb failed.");
}
- DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n",
- fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten ));
+ DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
+ "for file %s, offset %.0f, requested %u, written = %u\n",
+ fsp->fsp_name, (double)aio_ex->acb.aio_offset,
+ (unsigned int)numtowrite, (unsigned int)nwritten ));
return ret;
}
/****************************************************************************
- Handle any aio completion. Returns True if finished (and sets *perr if err was non-zero),
- False if not.
+ Handle any aio completion. Returns True if finished (and sets *perr if err
+ was non-zero), False if not.
*****************************************************************************/
static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr)
@@ -500,8 +534,9 @@ static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr)
/* Ensure the operation has really completed. */
if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) {
- DEBUG(10,( "handle_aio_completed: operation mid %u still in process for file %s\n",
- aio_ex->mid, aio_ex->fsp->fsp_name ));
+ DEBUG(10,( "handle_aio_completed: operation mid %u still in "
+ "process for file %s\n",
+ aio_ex->mid, aio_ex->fsp->fsp_name ));
return False;
}
@@ -530,8 +565,10 @@ int process_aio_queue(void)
BlockSignals(True, RT_SIGNAL_AIO);
- DEBUG(10,("process_aio_queue: signals_received = %d\n", (int)signals_received));
- DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", outstanding_aio_calls));
+ DEBUG(10,("process_aio_queue: signals_received = %d\n",
+ (int)signals_received));
+ DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n",
+ outstanding_aio_calls));
if (!signals_received) {
BlockSignals(False, RT_SIGNAL_AIO);
@@ -545,16 +582,18 @@ int process_aio_queue(void)
struct aio_extra *aio_ex = find_aio_ex(mid);
if (!aio_ex) {
- DEBUG(3,("process_aio_queue: Can't find record to match mid %u.\n",
- (unsigned int)mid));
+ DEBUG(3,("process_aio_queue: Can't find record to "
+ "match mid %u.\n", (unsigned int)mid));
srv_cancel_sign_response(mid);
continue;
}
fsp = aio_ex->fsp;
if (fsp == NULL) {
- /* file was closed whilst I/O was outstanding. Just ignore. */
- DEBUG( 3,( "process_aio_queue: file closed whilst aio outstanding.\n"));
+ /* file was closed whilst I/O was outstanding. Just
+ * ignore. */
+ DEBUG( 3,( "process_aio_queue: file closed whilst "
+ "aio outstanding.\n"));
srv_cancel_sign_response(mid);
continue;
}
@@ -573,23 +612,23 @@ int process_aio_queue(void)
}
/****************************************************************************
- We're doing write behind and the client closed the file. Wait up to 30 seconds
- (my arbitrary choice) for the aio to complete. Return 0 if all writes completed,
- errno to return if not.
+ We're doing write behind and the client closed the file. Wait up to 30
+ seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
+ completed, errno to return if not.
*****************************************************************************/
#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
-BOOL wait_for_aio_completion(files_struct *fsp)
+int wait_for_aio_completion(files_struct *fsp)
{
struct aio_extra *aio_ex;
const SMB_STRUCT_AIOCB **aiocb_list;
int aio_completion_count = 0;
time_t start_time = time(NULL);
int seconds_left;
- int ret = 0;
- for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) {
+ for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
+ seconds_left >= 0;) {
int err = 0;
int i;
struct timespec ts;
@@ -602,18 +641,21 @@ BOOL wait_for_aio_completion(files_struct *fsp)
}
if (!aio_completion_count) {
- return ret;
+ return 0;
}
- DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n",
- aio_completion_count ));
+ DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
+ "to complete.\n", aio_completion_count ));
- aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count);
+ aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
+ aio_completion_count);
if (!aiocb_list) {
- return False;
+ return ENOMEM;
}
- for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
+ for( i = 0, aio_ex = aio_list_head;
+ aio_ex;
+ aio_ex = aio_ex->next) {
if (aio_ex->fsp == fsp) {
aiocb_list[i++] = &aio_ex->acb;
}
@@ -623,32 +665,38 @@ BOOL wait_for_aio_completion(files_struct *fsp)
ts.tv_sec = seconds_left;
ts.tv_nsec = 0;
- DEBUG(10,("wait_for_aio_completion: %d events, doing a wait of %d seconds.\n",
- aio_completion_count, seconds_left ));
+ DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
+ "of %d seconds.\n",
+ aio_completion_count, seconds_left ));
- err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, aio_completion_count, &ts);
+ err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
+ aio_completion_count, &ts);
- DEBUG(10,("wait_for_aio_completion: returned err = %d, errno = %s\n",
- err, strerror(errno) ));
+ DEBUG(10,("wait_for_aio_completion: returned err = %d, "
+ "errno = %s\n", err, strerror(errno) ));
if (err == -1 && errno == EAGAIN) {
- DEBUG(0,("wait_for_aio_completion: aio_suspend timed out waiting for %d events after a wait of %d seconds\n",
- aio_completion_count, seconds_left));
+ DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
+ "out waiting for %d events after a wait of "
+ "%d seconds\n", aio_completion_count,
+ seconds_left));
/* Timeout. */
cancel_aio_by_fsp(fsp);
SAFE_FREE(aiocb_list);
- return ret ? ret : EIO;
+ return EIO;
}
- /* One or more events might have completed - process them if so. */
+ /* One or more events might have completed - process them if
+ * so. */
for( i = 0; i < aio_completion_count; i++) {
uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int;
aio_ex = find_aio_ex(mid);
if (!aio_ex) {
- DEBUG(0, ("wait_for_aio_completion: mid %u doesn't match an aio record\n",
- (unsigned int)mid ));
+ DEBUG(0, ("wait_for_aio_completion: mid %u "
+ "doesn't match an aio record\n",
+ (unsigned int)mid ));
continue;
}
@@ -659,14 +707,17 @@ BOOL wait_for_aio_completion(files_struct *fsp)
}
SAFE_FREE(aiocb_list);
- seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - (time(NULL) - start_time);
+ seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
+ - (time(NULL) - start_time);
}
- /* We timed out - we don't know why. Return ret if already an error, else EIO. */
- DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n",
- aio_completion_count));
+ /* We timed out - we don't know why. Return ret if already an error,
+ * else EIO. */
+ DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
+ "for %d events\n",
+ aio_completion_count));
- return ret ? ret : EIO;
+ return EIO;
}
/****************************************************************************
@@ -679,29 +730,16 @@ void cancel_aio_by_fsp(files_struct *fsp)
for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
if (aio_ex->fsp == fsp) {
- /* Don't delete the aio_extra record as we may have completed
- and don't yet know it. Just do the aio_cancel call and return. */
+ /* Don't delete the aio_extra record as we may have
+ completed and don't yet know it. Just do the
+ aio_cancel call and return. */
SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb);
- aio_ex->fsp = NULL; /* fsp will be closed when we return. */
+ aio_ex->fsp = NULL; /* fsp will be closed when we
+ * return. */
}
}
}
-/****************************************************************************
- Check if a buffer was stolen for aio use.
-*****************************************************************************/
-
-BOOL aio_inbuffer_in_use(char *inbuf)
-{
- struct aio_extra *aio_ex;
-
- for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
- if (aio_ex->inbuf == inbuf) {
- return True;
- }
- }
- return False;
-}
#else
BOOL aio_finished(void)
{
@@ -744,9 +782,4 @@ BOOL wait_for_aio_completion(files_struct *fsp)
{
return True;
}
-
-BOOL aio_inbuffer_in_use(char *ptr)
-{
- return False;
-}
#endif
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index a8db498ef5a..70b2d30aaba 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -19,6 +19,10 @@
*/
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
+extern int max_send;
/****************************************************************************
This is the structure to queue to implement blocking locks.
@@ -30,26 +34,29 @@ typedef struct _blocking_lock_record {
struct _blocking_lock_record *prev;
int com_type;
files_struct *fsp;
- time_t expire_time;
+ struct timeval expire_time;
int lock_num;
SMB_BIG_UINT offset;
SMB_BIG_UINT count;
- uint16 lock_pid;
+ uint32 lock_pid;
enum brl_flavour lock_flav;
enum brl_type lock_type;
char *inbuf;
int length;
} blocking_lock_record;
+/* dlink list we store pending lock records on. */
static blocking_lock_record *blocking_lock_queue;
+/* dlink list we move cancelled lock records onto. */
+static blocking_lock_record *blocking_lock_cancelled_queue;
+
/****************************************************************************
Destructor for the above structure.
****************************************************************************/
static void free_blocking_lock_record(blocking_lock_record *blr)
{
- DLIST_REMOVE(blocking_lock_queue, blr);
SAFE_FREE(blr->inbuf);
SAFE_FREE(blr);
}
@@ -64,25 +71,25 @@ static BOOL in_chained_smb(void)
}
static void received_unlock_msg(int msg_type, struct process_id src,
- void *buf, size_t len);
+ void *buf, size_t len,
+ void *private_data);
/****************************************************************************
Function to push a blocking lock request onto the lock queue.
****************************************************************************/
-BOOL push_blocking_lock_request( char *inbuf, int length,
+BOOL push_blocking_lock_request( struct byte_range_lock *br_lck,
+ char *inbuf, int length,
files_struct *fsp,
int lock_timeout,
int lock_num,
- uint16 lock_pid,
+ uint32 lock_pid,
enum brl_type lock_type,
enum brl_flavour lock_flav,
SMB_BIG_UINT offset, SMB_BIG_UINT count)
{
static BOOL set_lock_msg;
- blocking_lock_record *blr, *tmp;
- BOOL my_lock_ctx = False;
- struct byte_range_lock *br_lck = NULL;
+ blocking_lock_record *blr;
NTSTATUS status;
if(in_chained_smb() ) {
@@ -111,7 +118,13 @@ BOOL push_blocking_lock_request( char *inbuf, int length,
blr->com_type = CVAL(inbuf,smb_com);
blr->fsp = fsp;
- blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
+ if (lock_timeout == -1) {
+ blr->expire_time.tv_sec = 0;
+ blr->expire_time.tv_usec = 0; /* Never expire. */
+ } else {
+ blr->expire_time = timeval_current_ofs(lock_timeout/1000,
+ (lock_timeout % 1000) * 1000);
+ }
blr->lock_num = lock_num;
blr->lock_pid = lock_pid;
blr->lock_flav = lock_flav;
@@ -121,39 +134,36 @@ BOOL push_blocking_lock_request( char *inbuf, int length,
memcpy(blr->inbuf, inbuf, length);
blr->length = length;
- br_lck = brl_get_locks(blr->fsp);
- if (!br_lck) {
- free_blocking_lock_record(blr);
- return False;
- }
-
/* Add a pending lock record for this. */
status = brl_lock(br_lck,
lock_pid,
procid_self(),
offset,
count,
- PENDING_LOCK,
+ lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
blr->lock_flav,
- &my_lock_ctx);
- byte_range_lock_destructor(br_lck);
+ lock_timeout ? True : False); /* blocking_lock. */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
return False;
}
- DLIST_ADD_END(blocking_lock_queue, blr, tmp);
+ DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *);
/* Ensure we'll receive messages when this is unlocked. */
if (!set_lock_msg) {
- message_register(MSG_SMB_UNLOCK, received_unlock_msg);
+ message_register(MSG_SMB_UNLOCK, received_unlock_msg,
+ NULL);
set_lock_msg = True;
}
- DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \
-for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout,
+ DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with "
+ "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
+ length, (unsigned int)blr->expire_time.tv_sec,
+ (unsigned int)blr->expire_time.tv_usec, lock_timeout,
blr->fsp->fnum, blr->fsp->fsp_name ));
/* Push the MID of this packet on the signing queue. */
@@ -172,7 +182,7 @@ static void send_blocking_reply(char *outbuf, int outsize)
smb_setlen(outbuf,outsize - 4);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_blocking_reply: send_smb failed.");
+ exit_server_cleanly("send_blocking_reply: send_smb failed.");
}
/****************************************************************************
@@ -220,9 +230,24 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat
status = NT_STATUS_FILE_LOCK_CONFLICT;
}
+ if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
+ /* Store the last lock error. */
+ files_struct *fsp = blr->fsp;
+
+ fsp->last_lock_failure.context.smbpid = blr->lock_pid;
+ fsp->last_lock_failure.context.tid = fsp->conn->cnum;
+ fsp->last_lock_failure.context.pid = procid_self();
+ fsp->last_lock_failure.start = blr->offset;
+ fsp->last_lock_failure.size = blr->count;
+ fsp->last_lock_failure.fnum = fsp->fnum;
+ fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
+ fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ }
+
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("generic_blocking_lock_error: send_smb failed.");
+ if (!send_smb(smbd_server_fd(),outbuf)) {
+ exit_server_cleanly("generic_blocking_lock_error: send_smb failed.");
+ }
}
/****************************************************************************
@@ -236,7 +261,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
files_struct *fsp = blr->fsp;
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0;
- uint16 lock_pid;
+ uint32 lock_pid;
unsigned char locktype = CVAL(inbuf,smb_vwv3);
BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
char *data;
@@ -284,13 +309,6 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status)
{
switch(blr->com_type) {
-#if 0
- /* We no longer push blocking lock requests for anything but lockingX and trans2. */
- case SMBlock:
- case SMBlockread:
- generic_blocking_lock_error(blr, status);
- break;
-#endif
case SMBlockingX:
reply_lockingX_error(blr, status);
break;
@@ -306,7 +324,7 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status
SCVAL(outbuf,smb_com,SMBtrans2);
ERROR_NT(status);
if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("blocking_lock_reply_error: send_smb failed.");
+ exit_server_cleanly("blocking_lock_reply_error: send_smb failed.");
}
break;
}
@@ -316,148 +334,6 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status
}
}
-#if 0
-/* We no longer push blocking lock requests for anything but lockingX and trans2. */
-
-/****************************************************************************
- Attempt to finish off getting all pending blocking locks for a lockread call.
- Returns True if we want to be removed from the list.
-*****************************************************************************/
-
-static BOOL process_lockread(blocking_lock_record *blr)
-{
- char *outbuf = get_OutBuffer();
- char *inbuf = blr->inbuf;
- ssize_t nread = -1;
- char *data, *p;
- int outsize = 0;
- SMB_BIG_UINT startpos;
- size_t numtoread;
- NTSTATUS status;
- files_struct *fsp = blr->fsp;
- BOOL my_lock_ctx = False;
-
- numtoread = SVAL(inbuf,smb_vwv1);
- startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2);
-
- numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
- data = smb_buf(outbuf) + 3;
-
- status = do_lock_spin(fsp,
- SVAL(inbuf,smb_pid),
- (SMB_BIG_UINT)numtoread,
- startpos,
- READ_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
-
- if (NT_STATUS_V(status)) {
- if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
- !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
- /*
- * We have other than a "can't get lock"
- * error. Send an error.
- * Return True so we get dequeued.
- */
- generic_blocking_lock_error(blr, status);
- return True;
- }
-
- /*
- * Still waiting for lock....
- */
-
- DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n",
- fsp->fsp_name));
- return False;
- }
-
- nread = read_file(fsp,data,startpos,numtoread);
-
- if (nread < 0) {
- generic_blocking_lock_error(blr,NT_STATUS_ACCESS_DENIED);
- return True;
- }
-
- construct_reply_common(inbuf, outbuf);
- outsize = set_message(outbuf,5,0,True);
-
- outsize += nread;
- SSVAL(outbuf,smb_vwv0,nread);
- SSVAL(outbuf,smb_vwv5,nread+3);
- p = smb_buf(outbuf);
- *p++ = 1;
- SSVAL(p,0,nread); p += 2;
- set_message_end(outbuf, p+nread);
-
- DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n",
- fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) );
-
- send_blocking_reply(outbuf,outsize);
- return True;
-}
-
-/****************************************************************************
- Attempt to finish off getting all pending blocking locks for a lock call.
- Returns True if we want to be removed from the list.
-*****************************************************************************/
-
-static BOOL process_lock(blocking_lock_record *blr)
-{
- char *outbuf = get_OutBuffer();
- char *inbuf = blr->inbuf;
- int outsize;
- SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
- NTSTATUS status;
- files_struct *fsp = blr->fsp;
- BOOL my_lock_ctx = False;
-
- count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
- offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
-
- errno = 0;
- status = do_lock_spin(fsp,
- SVAL(inbuf,smb_pid),
- count,
- offset,
- WRITE_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
-
- if (NT_STATUS_IS_ERR(status)) {
- if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
- !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
- /*
- * We have other than a "can't get lock"
- * error. Send an error.
- * Return True so we get dequeued.
- */
-
- blocking_lock_reply_error(blr, status);
- return True;
- }
- /*
- * Still can't get the lock - keep waiting.
- */
- DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n",
- fsp->fsp_name));
- return False;
- }
-
- /*
- * Success - we got the lock.
- */
-
- DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n",
- fsp->fsp_name, fsp->fnum, (double)offset, (double)count));
-
- construct_reply_common(inbuf, outbuf);
- outsize = set_message(outbuf,0,0,True);
- send_blocking_reply(outbuf,outsize);
- return True;
-}
-#endif
-
/****************************************************************************
Attempt to finish off getting all pending blocking locks for a lockingX call.
Returns True if we want to be removed from the list.
@@ -471,10 +347,9 @@ static BOOL process_lockingX(blocking_lock_record *blr)
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
uint16 num_locks = SVAL(inbuf,smb_vwv7);
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
- uint16 lock_pid;
+ uint32 lock_pid;
BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
char *data;
- BOOL my_lock_ctx = False;
NTSTATUS status = NT_STATUS_OK;
data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks);
@@ -483,8 +358,9 @@ static BOOL process_lockingX(blocking_lock_record *blr)
* Data now points at the beginning of the list
* of smb_lkrng structs.
*/
-
+
for(; blr->lock_num < num_locks; blr->lock_num++) {
+ struct byte_range_lock *br_lck = NULL;
BOOL err;
lock_pid = get_lock_pid( data, blr->lock_num, large_file_format);
@@ -496,13 +372,17 @@ static BOOL process_lockingX(blocking_lock_record *blr)
* request would never have been queued. JRA.
*/
errno = 0;
- status = do_lock_spin(fsp,
+ br_lck = do_lock(fsp,
lock_pid,
count,
offset,
- ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
+ ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
+ READ_LOCK : WRITE_LOCK),
WINDOWS_LOCK,
- &my_lock_ctx);
+ True,
+ &status);
+
+ TALLOC_FREE(br_lck);
if (NT_STATUS_IS_ERR(status)) {
break;
@@ -549,20 +429,19 @@ Waiting....\n",
static BOOL process_trans2(blocking_lock_record *blr)
{
- extern int max_send;
char *inbuf = blr->inbuf;
char *outbuf;
- BOOL my_lock_ctx = False;
char params[2];
NTSTATUS status;
-
- status = do_lock(blr->fsp,
- blr->lock_pid,
- blr->count,
- blr->offset,
- blr->lock_type,
- blr->lock_flav,
- &my_lock_ctx);
+ struct byte_range_lock *br_lck = do_lock(blr->fsp,
+ blr->lock_pid,
+ blr->count,
+ blr->offset,
+ blr->lock_type,
+ blr->lock_flav,
+ True,
+ &status);
+ TALLOC_FREE(br_lck);
if (!NT_STATUS_IS_OK(status)) {
if (ERROR_WAS_LOCK_DENIED(status)) {
@@ -582,7 +461,8 @@ static BOOL process_trans2(blocking_lock_record *blr)
construct_reply_common(inbuf, outbuf);
SCVAL(outbuf,smb_com,SMBtrans2);
SSVAL(params,0,0);
- send_trans2_replies(outbuf, max_send, params, 2, NULL, 0);
+ /* Fake up max_data_bytes here - we know it fits. */
+ send_trans2_replies(outbuf, max_send, params, 2, NULL, 0, 0xffff);
return True;
}
@@ -595,13 +475,6 @@ static BOOL process_trans2(blocking_lock_record *blr)
static BOOL blocking_lock_record_process(blocking_lock_record *blr)
{
switch(blr->com_type) {
-#if 0
- /* We no longer push blocking lock requests for anything but lockingX and trans2. */
- case SMBlock:
- return process_lock(blr);
- case SMBlockread:
- return process_lockread(blr);
-#endif
case SMBlockingX:
return process_lockingX(blr);
case SMBtrans2:
@@ -615,33 +488,41 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr)
}
/****************************************************************************
- Delete entries by fnum from the blocking lock pending queue.
+ Cancel entries by fnum from the blocking lock pending queue.
*****************************************************************************/
-void remove_pending_lock_requests_by_fid(files_struct *fsp)
+void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
{
blocking_lock_record *blr, *next = NULL;
for(blr = blocking_lock_queue; blr; blr = next) {
next = blr->next;
if(blr->fsp->fnum == fsp->fnum) {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ unsigned char locktype = 0;
+
+ if (blr->com_type == SMBlockingX) {
+ locktype = CVAL(blr->inbuf,smb_vwv3);
+ }
if (br_lck) {
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ blocking_lock_cancel(fsp,
+ blr->lock_pid,
+ blr->offset,
+ blr->count,
+ blr->lock_flav,
+ locktype,
+ NT_STATUS_RANGE_NOT_LOCKED);
}
-
- free_blocking_lock_record(blr);
}
}
}
@@ -658,73 +539,108 @@ void remove_pending_lock_requests_by_mid(int mid)
next = blr->next;
if(SVAL(blr->inbuf,smb_mid) == mid) {
files_struct *fsp = blr->fsp;
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
if (br_lck) {
DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
}
}
}
/****************************************************************************
+ Is this mid a blocking lock request on the queue ?
+*****************************************************************************/
+
+BOOL blocking_lock_was_deferred(int mid)
+{
+ blocking_lock_record *blr, *next = NULL;
+
+ for(blr = blocking_lock_queue; blr; blr = next) {
+ next = blr->next;
+ if(SVAL(blr->inbuf,smb_mid) == mid) {
+ return True;
+ }
+ }
+ return False;
+}
+
+/****************************************************************************
Set a flag as an unlock request affects one of our pending locks.
*****************************************************************************/
static void received_unlock_msg(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
DEBUG(10,("received_unlock_msg\n"));
- process_blocking_lock_queue(time(NULL));
+ process_blocking_lock_queue();
}
/****************************************************************************
- Return the number of seconds to the next blocking locks timeout, or default_timeout
+ Return the number of milliseconds to the next blocking locks timeout, or default_timeout
*****************************************************************************/
-unsigned blocking_locks_timeout(unsigned default_timeout)
+unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms)
{
- unsigned timeout = default_timeout;
- time_t t;
+ unsigned int timeout_ms = default_timeout_ms;
+ struct timeval tv_curr;
+ SMB_BIG_INT min_tv_dif_us = 0x7FFFFFFF; /* A large +ve number. */
blocking_lock_record *blr = blocking_lock_queue;
- /* note that we avoid the time() syscall if there are no blocking locks */
- if (!blr)
- return timeout;
+ /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */
+ if (!blr) {
+ return timeout_ms;
+ }
- t = time(NULL);
+ tv_curr = timeval_current();
for (; blr; blr = blr->next) {
- if ((blr->expire_time != (time_t)-1) &&
- (timeout > (blr->expire_time - t))) {
- timeout = blr->expire_time - t;
+ SMB_BIG_INT tv_dif_us;
+
+ if (timeval_is_zero(&blr->expire_time)) {
+ continue; /* Never timeout. */
}
+
+ tv_dif_us = usec_time_diff(&blr->expire_time, &tv_curr);
+ min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us);
}
- if (timeout < 1)
- timeout = 1;
+ if (min_tv_dif_us < 0) {
+ min_tv_dif_us = 0;
+ }
- return timeout;
+ timeout_ms = (unsigned int)(min_tv_dif_us / (SMB_BIG_INT)1000);
+
+ if (timeout_ms < 1) {
+ timeout_ms = 1;
+ }
+
+ DEBUG(10,("blocking_locks_timeout_ms: returning %u\n", timeout_ms));
+
+ return timeout_ms;
}
/****************************************************************************
Process the blocking lock queue. Note that this is only called as root.
*****************************************************************************/
-void process_blocking_lock_queue(time_t t)
+void process_blocking_lock_queue(void)
{
+ struct timeval tv_curr = timeval_current();
blocking_lock_record *blr, *next = NULL;
/*
@@ -753,8 +669,8 @@ void process_blocking_lock_queue(time_t t)
DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
fsp->fnum, fsp->fsp_name ));
- if((blr->expire_time != -1) && (blr->expire_time <= t)) {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
/*
* Lock expired - throw away all previously
@@ -765,63 +681,66 @@ void process_blocking_lock_queue(time_t t)
DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
fsp->fnum, fsp->fsp_name ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
continue;
}
if(!change_to_user(conn,vuid)) {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
/*
* Remove the entry and return an error to the client.
*/
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
vuid ));
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
continue;
}
if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
/*
* Remove the entry and return an error to the client.
*/
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
change_to_root_user();
continue;
@@ -834,20 +753,118 @@ void process_blocking_lock_queue(time_t t)
*/
if(blocking_lock_record_process(blr)) {
- struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- byte_range_lock_destructor(br_lck);
+ TALLOC_FREE(br_lck);
}
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
}
change_to_root_user();
}
}
+
+/****************************************************************************
+ Handle a cancel message. Lock already moved onto the cancel queue.
+*****************************************************************************/
+
+#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS))
+
+static void process_blocking_lock_cancel_message(int msg_type,
+ struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
+{
+ NTSTATUS err;
+ const char *msg = (const char *)buf;
+ blocking_lock_record *blr;
+
+ if (buf == NULL) {
+ smb_panic("process_blocking_lock_cancel_message: null msg\n");
+ }
+
+ if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
+ DEBUG(0, ("process_blocking_lock_cancel_message: "
+ "Got invalid msg len %d\n", (int)len));
+ smb_panic("process_blocking_lock_cancel_message: bad msg\n");
+ }
+
+ memcpy(&blr, msg, sizeof(blr));
+ memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
+
+ DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
+ nt_errstr(err) ));
+
+ blocking_lock_reply_error(blr, err);
+ DLIST_REMOVE(blocking_lock_cancelled_queue, blr);
+ free_blocking_lock_record(blr);
+}
+
+/****************************************************************************
+ Send ourselves a blocking lock cancelled message. Handled asynchronously above.
+*****************************************************************************/
+
+BOOL blocking_lock_cancel(files_struct *fsp,
+ uint32 lock_pid,
+ SMB_BIG_UINT offset,
+ SMB_BIG_UINT count,
+ enum brl_flavour lock_flav,
+ unsigned char locktype,
+ NTSTATUS err)
+{
+ static BOOL initialized;
+ char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
+ blocking_lock_record *blr;
+
+ if (!initialized) {
+ /* Register our message. */
+ message_register(MSG_SMB_BLOCKING_LOCK_CANCEL,
+ process_blocking_lock_cancel_message,
+ NULL);
+
+ initialized = True;
+ }
+
+ for (blr = blocking_lock_queue; blr; blr = blr->next) {
+ if (fsp == blr->fsp &&
+ lock_pid == blr->lock_pid &&
+ offset == blr->offset &&
+ count == blr->count &&
+ lock_flav == blr->lock_flav) {
+ break;
+ }
+ }
+
+ if (!blr) {
+ return False;
+ }
+
+ /* Check the flags are right. */
+ if (blr->com_type == SMBlockingX &&
+ (locktype & LOCKING_ANDX_LARGE_FILES) !=
+ (CVAL(blr->inbuf,smb_vwv3) & LOCKING_ANDX_LARGE_FILES)) {
+ return False;
+ }
+
+ /* Move to cancelled queue. */
+ DLIST_REMOVE(blocking_lock_queue, blr);
+ DLIST_ADD(blocking_lock_cancelled_queue, blr);
+
+ /* Create the message. */
+ memcpy(msg, &blr, sizeof(blr));
+ memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
+
+ message_send_pid(pid_to_procid(sys_getpid()),
+ MSG_SMB_BLOCKING_LOCK_CANCEL,
+ &msg, sizeof(msg), True);
+
+ return True;
+}
diff --git a/source/smbd/change_trust_pw.c b/source/smbd/change_trust_pw.c
index 738d12151db..31f03cc7fad 100644
--- a/source/smbd/change_trust_pw.c
+++ b/source/smbd/change_trust_pw.c
@@ -79,17 +79,19 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n",
dc_name, nt_errstr(nt_status)));
cli_shutdown(cli);
+ cli = NULL;
goto failed;
}
nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain);
cli_shutdown(cli);
+ cli = NULL;
failed:
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n",
- timestring(False), domain));
+ current_timestring(False), domain));
}
else
DEBUG(5,("change_trust_account_password: sucess!\n"));
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index cd847240ddb..7c6886b81c9 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -689,7 +689,7 @@ BOOL change_lanman_password(struct samu *sampass, uchar *pass2)
return False; /* We lose the NT hash. Sorry. */
}
- if (!pdb_set_pass_changed_now (sampass)) {
+ if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) {
TALLOC_FREE(sampass);
/* Not quite sure what this one qualifies as, but this will do */
return False;
@@ -1018,41 +1018,34 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext)
NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)
{
- uint32 min_len, min_age;
+ uint32 min_len;
struct passwd *pass = NULL;
const char *username = pdb_get_username(hnd);
- time_t last_change_time = pdb_get_pass_last_set_time(hnd);
time_t can_change_time = pdb_get_pass_can_change_time(hnd);
if (samr_reject_reason) {
*samr_reject_reason = Undefined;
}
- if (pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age)) {
- /*
- * Windows calculates the minimum password age check
- * dynamically, it basically ignores the pwdcanchange
- * timestamp. Do likewise.
- */
- if (last_change_time + min_age > time(NULL)) {
- DEBUG(1, ("user %s cannot change password now, must "
- "wait until %s\n", username,
- http_timestring(last_change_time+min_age)));
- if (samr_reject_reason) {
- *samr_reject_reason = REJECT_REASON_OTHER;
- }
- return NT_STATUS_ACCOUNT_RESTRICTION;
+ /* check to see if the secdesc has previously been set to disallow */
+ if (!pdb_get_pass_can_change(hnd)) {
+ DEBUG(1, ("user %s does not have permissions to change password\n", username));
+ if (samr_reject_reason) {
+ *samr_reject_reason = REJECT_REASON_OTHER;
}
- } else {
- if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
- DEBUG(1, ("user %s cannot change password now, must "
- "wait until %s\n", username,
- http_timestring(can_change_time)));
- if (samr_reject_reason) {
- *samr_reject_reason = REJECT_REASON_OTHER;
- }
- return NT_STATUS_ACCOUNT_RESTRICTION;
+ return NT_STATUS_ACCOUNT_RESTRICTION;
+ }
+
+ /* removed calculation here, becuase passdb now calculates
+ based on policy. jmcd */
+ if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
+ DEBUG(1, ("user %s cannot change password now, must "
+ "wait until %s\n", username,
+ http_timestring(can_change_time)));
+ if (samr_reject_reason) {
+ *samr_reject_reason = REJECT_REASON_OTHER;
}
+ return NT_STATUS_ACCOUNT_RESTRICTION;
}
if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
diff --git a/source/smbd/close.c b/source/smbd/close.c
index 8a63d3b227b..b826cd622af 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
file closing
Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) Jeremy Allison 1992-2004.
+ Copyright (C) Jeremy Allison 1992-2007.
Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,8 @@
#include "includes.h"
+extern struct current_user current_user;
+
/****************************************************************************
Run a file if it is a magic script.
****************************************************************************/
@@ -88,22 +90,21 @@ static void check_magic(files_struct *fsp,connection_struct *conn)
Common code to close a file or a directory.
****************************************************************************/
-static int close_filestruct(files_struct *fsp)
+static NTSTATUS close_filestruct(files_struct *fsp)
{
+ NTSTATUS status = NT_STATUS_OK;
connection_struct *conn = fsp->conn;
- int ret = 0;
if (fsp->fh->fd != -1) {
- if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
- ret = -1;
-
+ if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
+ status = map_nt_error_from_unix(errno);
+ }
delete_write_cache(fsp);
}
conn->num_files_open--;
SAFE_FREE(fsp->wbmpx_ptr);
-
- return ret;
+ return status;
}
/****************************************************************************
@@ -134,10 +135,8 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
share_mode_entry_to_message(msg, e);
- become_root();
message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
- unbecome_root();
}
}
}
@@ -146,11 +145,14 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
Deal with removing a share mode on last close.
****************************************************************************/
-static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_remove_share_mode(files_struct *fsp,
+ enum file_close_type close_type)
{
connection_struct *conn = fsp->conn;
BOOL delete_file = False;
struct share_mode_lock *lck;
+ SMB_STRUCT_STAT sbuf;
+ NTSTATUS status = NT_STATUS_OK;
/*
* Lock the share entries, and determine if we should delete
@@ -161,22 +163,44 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
- DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name));
- return EINVAL;
+ DEBUG(0, ("close_remove_share_mode: Could not get share mode "
+ "lock for file %s\n", fsp->fsp_name));
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name));
+ DEBUG(0, ("close_remove_share_mode: Could not delete share "
+ "entry for file %s\n", fsp->fsp_name));
+ }
+
+ if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set and no one else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(conn, fsp->vuid);
+ became_user = True;
+ }
+ set_delete_on_close_lck(lck, True, &current_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
}
- delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
+ delete_file = lck->delete_on_close;
if (delete_file) {
int i;
/* See if others still have the file open. If this is the
- * case, then don't delete */
+ * case, then don't delete. If all opens are POSIX delete now. */
for (i=0; i<lck->num_share_modes; i++) {
- if (is_valid_share_mode_entry(&lck->share_modes[i])) {
+ struct share_mode_entry *e = &lck->share_modes[i];
+ if (is_valid_share_mode_entry(e)) {
+ if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+ continue;
+ }
delete_file = False;
break;
}
@@ -192,65 +216,93 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close
* reference to a file.
*/
- if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
- delete_file &&
- lck->delete_token) {
- SMB_STRUCT_STAT sbuf;
+ if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
+ || !delete_file
+ || (lck->delete_token == NULL)) {
+ TALLOC_FREE(lck);
+ return NT_STATUS_OK;
+ }
- DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set - deleting file.\n",
- fsp->fsp_name));
+ /*
+ * Ok, we have to delete the file
+ */
- /* Become the user who requested the delete. */
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
+ "- deleting file.\n", fsp->fsp_name));
- if (!push_sec_ctx()) {
- smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n");
- }
+ /* Become the user who requested the delete. */
- set_sec_ctx(lck->delete_token->uid,
- lck->delete_token->gid,
- lck->delete_token->ngroups,
- lck->delete_token->groups,
- NULL);
+ if (!push_sec_ctx()) {
+ smb_panic("close_remove_share_mode: file %s. failed to push "
+ "sec_ctx.\n");
+ }
- /* We can only delete the file if the name we have
- is still valid and hasn't been renamed. */
-
- if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
- DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
- "and stat failed with error %s\n",
- fsp->fsp_name, strerror(errno) ));
- } else {
- if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
- DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and "
- "dev and/or inode does not match\n",
- fsp->fsp_name ));
- DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f "
- "stat dev = %x, inode = %.0f\n",
- fsp->fsp_name,
- (unsigned int)fsp->dev, (double)fsp->inode,
- (unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
-
- } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
- /*
- * This call can potentially fail as another smbd may have
- * had the file open with delete on close set and deleted
- * it when its last reference to this file went away. Hence
- * we log this but not at debug level zero.
- */
-
- DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
- "and unlink failed with error %s\n",
- fsp->fsp_name, strerror(errno) ));
- }
- }
- /* unbecome user. */
- pop_sec_ctx();
+ set_sec_ctx(lck->delete_token->uid,
+ lck->delete_token->gid,
+ lck->delete_token->ngroups,
+ lck->delete_token->groups,
+ NULL);
+
+ /* We can only delete the file if the name we have is still valid and
+ hasn't been renamed. */
- process_pending_change_notify_queue((time_t)0);
+ if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
+ "was set and stat failed with error %s\n",
+ fsp->fsp_name, strerror(errno) ));
+ /*
+ * Don't save the errno here, we ignore this error
+ */
+ goto done;
+ }
+
+ if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
+ "was set and dev and/or inode does not match\n",
+ fsp->fsp_name ));
+ DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, "
+ "inode = %.0f stat dev = %x, inode = %.0f\n",
+ fsp->fsp_name,
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ (unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
+ /*
+ * Don't save the errno here, we ignore this error
+ */
+ goto done;
}
+ if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
+ /*
+ * This call can potentially fail as another smbd may
+ * have had the file open with delete on close set and
+ * deleted it when its last reference to this file
+ * went away. Hence we log this but not at debug level
+ * zero.
+ */
+
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
+ "was set and unlink failed with error %s\n",
+ fsp->fsp_name, strerror(errno) ));
+
+ status = map_nt_error_from_unix(errno);
+ }
+
+ /* As we now have POSIX opens which can unlink
+ * with other open files we may have taken
+ * this code path with more than one share mode
+ * entry - ensure we only delete once by resetting
+ * the delete on close flag. JRA.
+ */
+
+ set_delete_on_close_lck(lck, False, NULL);
+
+ done:
+
+ /* unbecome user. */
+ pop_sec_ctx();
+
TALLOC_FREE(lck);
- return 0;
+ return status;
}
/****************************************************************************
@@ -261,14 +313,13 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close
delete on close is done on normal and shutdown close.
****************************************************************************/
-static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
{
+ NTSTATUS status = NT_STATUS_OK;
+ NTSTATUS saved_status1 = NT_STATUS_OK;
+ NTSTATUS saved_status2 = NT_STATUS_OK;
+ NTSTATUS saved_status3 = NT_STATUS_OK;
connection_struct *conn = fsp->conn;
- int saved_errno = 0;
- int err = 0;
- int err1 = 0;
-
- remove_pending_lock_requests_by_fid(fsp);
if (fsp->aio_write_behind) {
/*
@@ -277,8 +328,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
*/
int ret = wait_for_aio_completion(fsp);
if (ret) {
- saved_errno = ret;
- err1 = -1;
+ saved_status1 = map_nt_error_from_unix(ret);
}
} else {
cancel_aio_by_fsp(fsp);
@@ -289,15 +339,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
* error here, we must remember this.
*/
- if (close_filestruct(fsp) == -1) {
- saved_errno = errno;
- err1 = -1;
- }
+ saved_status2 = close_filestruct(fsp);
if (fsp->print_file) {
print_fsp_end(fsp, close_type);
file_free(fsp);
- return 0;
+ return NT_STATUS_OK;
}
/* If this is an old DOS or FCB open and we have multiple opens on
@@ -306,7 +353,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
if (fsp->fh->ref_count == 1) {
/* Should we return on error here... ? */
- close_remove_share_mode(fsp, close_type);
+ saved_status3 = close_remove_share_mode(fsp, close_type);
}
if(fsp->oplock_type) {
@@ -315,13 +362,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
locking_close_file(fsp);
- err = fd_close(conn, fsp);
-
- /* Only save errno if fd_close failed and we don't already
- have an errno saved from a flush call. */
- if ((err1 != -1) && (err == -1)) {
- saved_errno = errno;
- }
+ status = fd_close(conn, fsp);
/* check for magic scripts */
if (close_type == NORMAL_CLOSE) {
@@ -338,29 +379,34 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
}
+ if (NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(saved_status1)) {
+ status = saved_status1;
+ } else if (!NT_STATUS_IS_OK(saved_status2)) {
+ status = saved_status2;
+ } else if (!NT_STATUS_IS_OK(saved_status3)) {
+ status = saved_status3;
+ }
+ }
+
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
conn->user,fsp->fsp_name,
conn->num_files_open,
- (err == -1 || err1 == -1) ? strerror(saved_errno) : ""));
+ nt_errstr(status) ));
file_free(fsp);
-
- if (err == -1 || err1 == -1) {
- errno = saved_errno;
- return saved_errno;
- } else {
- return 0;
- }
+ return status;
}
/****************************************************************************
Close a directory opened by an NT SMB call.
****************************************************************************/
-static int close_directory(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
{
struct share_mode_lock *lck = 0;
BOOL delete_dir = False;
+ NTSTATUS status = NT_STATUS_OK;
/*
* NT can set delete_on_close of the last open
@@ -371,19 +417,52 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
- return EINVAL;
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!del_share_mode(lck, fsp)) {
DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
}
- delete_dir = (lck->delete_on_close | lck->initial_delete_on_close);
+ if (fsp->initial_delete_on_close) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set - for
+ * directories we don't care if anyone else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(fsp->conn, fsp->vuid);
+ became_user = True;
+ }
+ send_stat_cache_delete_message(fsp->fsp_name);
+ set_delete_on_close_lck(lck, True, &current_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
+ }
+
+ delete_dir = lck->delete_on_close;
+
+ if (delete_dir) {
+ int i;
+ /* See if others still have the dir open. If this is the
+ * case, then don't delete. If all opens are POSIX delete now. */
+ for (i=0; i<lck->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->share_modes[i];
+ if (is_valid_share_mode_entry(e)) {
+ if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+ continue;
+ }
+ delete_dir = False;
+ break;
+ }
+ }
+ }
if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
delete_dir &&
lck->delete_token) {
- BOOL ok;
/* Become the user who requested the delete. */
@@ -399,10 +478,11 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
TALLOC_FREE(lck);
- ok = rmdir_internals(fsp->conn, fsp->fsp_name);
+ status = rmdir_internals(fsp->conn, fsp->fsp_name);
- DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
- fsp->fsp_name, ok ? "succeeded" : "failed" ));
+ DEBUG(5,("close_directory: %s. Delete on close was set - "
+ "deleting directory returned %s.\n",
+ fsp->fsp_name, nt_errstr(status)));
/* unbecome user. */
pop_sec_ctx();
@@ -412,15 +492,13 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
* now fail as the directory has been deleted.
*/
- if(ok) {
+ if(NT_STATUS_IS_OK(status)) {
remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
- remove_pending_change_notify_requests_by_filename(fsp, NT_STATUS_DELETE_PENDING);
-
}
- process_pending_change_notify_queue((time_t)0);
} else {
TALLOC_FREE(lck);
- remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_CANCELLED);
+ remove_pending_change_notify_requests_by_fid(
+ fsp, NT_STATUS_OK);
}
/*
@@ -428,35 +506,35 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
*/
close_filestruct(fsp);
file_free(fsp);
- return 0;
+ return status;
}
/****************************************************************************
Close a 'stat file' opened internally.
****************************************************************************/
-static int close_stat(files_struct *fsp)
+NTSTATUS close_stat(files_struct *fsp)
{
/*
* Do the code common to files and directories.
*/
close_filestruct(fsp);
file_free(fsp);
- return 0;
+ return NT_STATUS_OK;
}
/****************************************************************************
Close a files_struct.
****************************************************************************/
-int close_file(files_struct *fsp, enum file_close_type close_type)
+NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
{
- if(fsp->is_directory)
+ if(fsp->is_directory) {
return close_directory(fsp, close_type);
- else if (fsp->is_stat)
+ } else if (fsp->is_stat) {
return close_stat(fsp);
- else if (fsp->fake_file_handle != NULL)
+ } else if (fsp->fake_file_handle != NULL) {
return close_fake_file(fsp);
- else
- return close_normal_file(fsp, close_type);
+ }
+ return close_normal_file(fsp, close_type);
}
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index c79f7641522..44888b777f2 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -57,7 +57,7 @@ BOOL conn_snum_used(int snum)
{
connection_struct *conn;
for (conn=Connections;conn;conn=conn->next) {
- if (conn->service == snum) {
+ if (conn->params->service == snum) {
return(True);
}
}
@@ -107,7 +107,7 @@ find_again:
int newsz = bmap->n + BITMAP_BLOCK_SZ;
struct bitmap * nbmap;
- if (newsz <= 0) {
+ if (newsz <= oldsz) {
/* Integer wrap. */
DEBUG(0,("ERROR! Out of connection structures\n"));
return NULL;
@@ -131,13 +131,25 @@ find_again:
goto find_again;
}
+ /* The bitmap position is used below as the connection number
+ * conn->cnum). This ends up as the TID field in the SMB header,
+ * which is limited to 16 bits (we skip 0xffff which is the
+ * NULL TID).
+ */
+ if (i > 65534) {
+ DEBUG(0, ("Maximum connection limit reached\n"));
+ return NULL;
+ }
+
if ((mem_ctx=talloc_init("connection_struct"))==NULL) {
DEBUG(0,("talloc_init(connection_struct) failed!\n"));
return NULL;
}
- if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) {
+ if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) ||
+ !(conn->params = TALLOC_P(mem_ctx, struct share_params))) {
DEBUG(0,("talloc_zero() failed!\n"));
+ TALLOC_FREE(mem_ctx);
return NULL;
}
conn->mem_ctx = mem_ctx;
@@ -245,6 +257,7 @@ void conn_free_internal(connection_struct *conn)
{
vfs_handle_struct *handle = NULL, *thandle = NULL;
TALLOC_CTX *mem_ctx = NULL;
+ struct trans_state *state = NULL;
/* Free vfs_connection_struct */
handle = conn->vfs_handles;
@@ -256,13 +269,11 @@ void conn_free_internal(connection_struct *conn)
handle = thandle;
}
- if (conn->ngroups && conn->groups) {
- SAFE_FREE(conn->groups);
- conn->ngroups = 0;
- }
-
- if (conn->nt_user_token) {
- TALLOC_FREE(conn->nt_user_token);
+ /* Free any pending transactions stored on this conn. */
+ for (state = conn->pending_trans; state; state = state->next) {
+ /* state->setup is a talloc child of state. */
+ SAFE_FREE(state->param);
+ SAFE_FREE(state->data);
}
free_namearray(conn->veto_list);
@@ -300,7 +311,8 @@ the message contains just a share name and all instances of that
share are unmounted
the special sharename '*' forces unmount of all shares
****************************************************************************/
-void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len)
+void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len,
+ void *private_data)
{
connection_struct *conn, *next;
fstring sharename;
@@ -315,7 +327,7 @@ void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len)
for (conn=Connections;conn;conn=next) {
next=conn->next;
- if (strequal(lp_servicename(conn->service), sharename)) {
+ if (strequal(lp_servicename(SNUM(conn)), sharename)) {
DEBUG(1,("Forcing close of share %s cnum=%d\n",
sharename, conn->cnum));
close_cnum(conn, (uint16)-1);
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 07d3181144f..0442a9441ad 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -83,7 +83,7 @@ BOOL yield_connection(connection_struct *conn, const char *name)
struct count_stat {
pid_t mypid;
int curr_connections;
- char *name;
+ const char *name;
BOOL Clear;
};
@@ -124,43 +124,55 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
Claim an entry in the connections database.
****************************************************************************/
-BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
+int count_current_connections( const char *sharename, BOOL clear )
{
- struct connections_key key;
- struct connections_data crec;
- TDB_DATA kbuf, dbuf;
-
- if (!tdb)
- tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
- O_RDWR | O_CREAT, 0644);
+ struct count_stat cs;
- if (!tdb)
- return False;
+ cs.mypid = sys_getpid();
+ cs.curr_connections = 0;
+ cs.name = sharename;
+ cs.Clear = clear;
/*
- * Enforce the max connections parameter.
+ * This has a race condition, but locking the chain before hand is worse
+ * as it leads to deadlock.
*/
- if (max_connections > 0) {
- struct count_stat cs;
+ if (tdb_traverse(tdb, count_fn, &cs) == -1) {
+ DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
+ tdb_errorstr(tdb) ));
+ return False;
+ }
+
+ return cs.curr_connections;
+}
- cs.mypid = sys_getpid();
- cs.curr_connections = 0;
- cs.name = lp_servicename(SNUM(conn));
- cs.Clear = Clear;
+/****************************************************************************
+ Claim an entry in the connections database.
+****************************************************************************/
- /*
- * This has a race condition, but locking the chain before hand is worse
- * as it leads to deadlock.
- */
+BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
+{
+ struct connections_key key;
+ struct connections_data crec;
+ TDB_DATA kbuf, dbuf;
- if (tdb_traverse(tdb, count_fn, &cs) == -1) {
- DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
- tdb_errorstr(tdb) ));
+ if (!tdb) {
+ if ( (tdb =conn_tdb_ctx()) == NULL ) {
return False;
}
+ }
+
+ /*
+ * Enforce the max connections parameter.
+ */
- if (cs.curr_connections >= max_connections) {
+ if (max_connections > 0) {
+ int curr_connections;
+
+ curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True );
+
+ if (curr_connections >= max_connections) {
DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
max_connections, name ));
return False;
@@ -241,3 +253,108 @@ BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
SAFE_FREE(dbuf.dptr);
return True;
}
+
+/*********************************************************************
+*********************************************************************/
+
+static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec )
+{
+ TDB_DATA *kbuf = NULL;
+ fstring key_string;
+
+ if ( !prec )
+ return NULL;
+
+ if ( (kbuf = TALLOC_P(prec, TDB_DATA)) == NULL ) {
+ return NULL;
+ }
+
+ snprintf( key_string, sizeof(key_string), "%s/%d/%d",
+ prec->name, procid_to_pid(&prec->pid), prec->pnum );
+
+ if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL )
+ return NULL;
+
+ kbuf->dsize = strlen(key_string)+1;
+
+ return kbuf;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p )
+{
+ prec->pid = pid_to_procid(sys_getpid());
+ prec->pnum = p->pnum;
+ prec->uid = geteuid();
+ fstrcpy( prec->name, p->name );
+
+ return;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+BOOL store_pipe_opendb( smb_np_struct *p )
+{
+ struct pipe_open_rec *prec;
+ TDB_DATA *key;
+ TDB_DATA data;
+ TDB_CONTEXT *pipe_tdb;
+ BOOL ret = False;
+
+ if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
+ DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
+ return False;
+ }
+
+ fill_pipe_open_rec( prec, p );
+ if ( (key = make_pipe_rec_key( prec )) == NULL ) {
+ goto done;
+ }
+
+ data.dptr = (char*)prec;
+ data.dsize = sizeof(struct pipe_open_rec);
+
+ if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
+ goto done;
+ }
+
+ ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1);
+
+done:
+ TALLOC_FREE( prec );
+ return ret;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+BOOL delete_pipe_opendb( smb_np_struct *p )
+{
+ struct pipe_open_rec *prec;
+ TDB_DATA *key;
+ TDB_CONTEXT *pipe_tdb;
+ BOOL ret = False;
+
+ if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
+ DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
+ return False;
+ }
+
+ fill_pipe_open_rec( prec, p );
+ if ( (key = make_pipe_rec_key( prec )) == NULL ) {
+ goto done;
+ }
+
+ if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
+ goto done;
+ }
+
+ ret = (tdb_delete( pipe_tdb, *key ) != -1 );
+
+done:
+ TALLOC_FREE( prec );
+ return ret;
+}
diff --git a/source/smbd/dfree.c b/source/smbd/dfree.c
index dad7d917e8e..c488add227a 100644
--- a/source/smbd/dfree.c
+++ b/source/smbd/dfree.c
@@ -66,7 +66,7 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,
SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query,
SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
{
- int dfree_retval;
+ SMB_BIG_UINT dfree_retval;
SMB_BIG_UINT dfree_q = 0;
SMB_BIG_UINT bsize_q = 0;
SMB_BIG_UINT dsize_q = 0;
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index 8fbb565efe1..2795b2a24b2 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -382,21 +382,24 @@ static void dptr_close_oldest(BOOL old)
wcard must not be zero.
****************************************************************************/
-int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
- const char *wcard, BOOL wcard_has_wild, uint32 attr)
+NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
+ const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
{
struct dptr_struct *dptr = NULL;
struct smb_Dir *dir_hnd;
const char *dir2;
+ NTSTATUS status;
DEBUG(5,("dptr_create dir=%s\n", path));
if (!wcard) {
- return -1;
+ return NT_STATUS_INVALID_PARAMETER;
}
- if (!check_name(path,conn))
- return(-2); /* Code to say use a unix error return code. */
+ status = check_name(conn,path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
/* use a const pointer from here on */
dir2 = path;
@@ -405,19 +408,20 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
dir_hnd = OpenDir(conn, dir2, wcard, attr);
if (!dir_hnd) {
- return (-2);
+ return map_nt_error_from_unix(errno);
}
string_set(&conn->dirpath,dir2);
- if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
+ if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
dptr_idleoldest();
+ }
dptr = SMB_MALLOC_P(struct dptr_struct);
if(!dptr) {
DEBUG(0,("malloc fail in dptr_create.\n"));
CloseDir(dir_hnd);
- return -1;
+ return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCTP(dptr);
@@ -447,7 +451,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
CloseDir(dir_hnd);
- return -1;
+ return NT_STATUS_TOO_MANY_OPENED_FILES;
}
}
} else {
@@ -477,7 +481,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
CloseDir(dir_hnd);
- return -1;
+ return NT_STATUS_TOO_MANY_OPENED_FILES;
}
}
}
@@ -496,7 +500,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
bitmap_clear(dptr_bmap, dptr->dnum - 1);
SAFE_FREE(dptr);
CloseDir(dir_hnd);
- return -1;
+ return NT_STATUS_NO_MEMORY;
}
if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
dptr->has_wild = True;
@@ -511,9 +515,9 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
dptr->dnum,path,expect_close));
- conn->dirptr = dptr;
+ *dptr_ret = dptr;
- return(dptr->dnum);
+ return NT_STATUS_OK;
}
@@ -523,6 +527,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
int dptr_CloseDir(struct dptr_struct *dptr)
{
+ DLIST_REMOVE(dirptrs, dptr);
return CloseDir(dptr->dir_hnd);
}
@@ -541,6 +546,11 @@ BOOL dptr_has_wild(struct dptr_struct *dptr)
return dptr->has_wild;
}
+int dptr_dnum(struct dptr_struct *dptr)
+{
+ return dptr->dnum;
+}
+
/****************************************************************************
Return the next visible file name, skipping veto'd and invisible files.
****************************************************************************/
@@ -752,7 +762,7 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
{
- mangle_map(filename,True,False,SNUM(conn));
+ mangle_map(filename,True,False,conn->params);
return mask_match_search(filename,mask,False);
}
@@ -798,8 +808,9 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
mask_match_search(filename,mask,False) ||
mangle_mask_match(conn,filename,mask)) {
- if (!mangle_is_8_3(filename, False, SNUM(conn)))
- mangle_map(filename,True,False,SNUM(conn));
+ if (!mangle_is_8_3(filename, False, conn->params))
+ mangle_map(filename,True,False,
+ conn->params);
pstrcpy(fname,filename);
*path = 0;
@@ -868,17 +879,18 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
/* Pseudo-open the file (note - no fd's created). */
if(S_ISDIR(pst->st_mode)) {
- fsp = open_directory(conn, name, pst,
+ status = open_directory(conn, name, pst,
READ_CONTROL_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0, /* no create options. */
- NULL);
+ FILE_ATTRIBUTE_DIRECTORY,
+ NULL, &fsp);
} else {
- fsp = open_file_stat(conn, name, pst);
+ status = open_file_stat(conn, name, pst, &fsp);
}
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
return False;
}
@@ -931,17 +943,17 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
if(S_ISDIR(pst->st_mode)) {
return True;
} else {
- fsp = open_file_ntcreate(conn, name, pst,
+ status = open_file_ntcreate(conn, name, pst,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
INTERNAL_OPEN_ONLY,
- &info);
+ &info, &fsp);
}
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
return False;
}
@@ -1010,6 +1022,18 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
return False;
}
+
+ /* If it's a dfs symlink, ignore _hide xxxx_ options */
+ if (lp_host_msdfs() &&
+ lp_msdfs_root(SNUM(conn)) &&
+ /* We get away with NULL talloc ctx here as
+ we're not interested in the link contents
+ so we have nothing to free. */
+ is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) {
+ SAFE_FREE(entry);
+ return True;
+ }
+
/* Honour _hide unreadable_ option */
if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
@@ -1255,3 +1279,42 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
}
return False;
}
+
+/*****************************************************************
+ Is this directory empty ?
+*****************************************************************/
+
+NTSTATUS can_delete_directory(struct connection_struct *conn,
+ const char *dirname)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ long dirpos = 0;
+ const char *dname;
+ struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
+
+ if (!dir_hnd) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
+ SMB_STRUCT_STAT st;
+
+ /* Quick check for "." and ".." */
+ if (dname[0] == '.') {
+ if (!dname[1] || (dname[1] == '.' && !dname[2])) {
+ continue;
+ }
+ }
+
+ if (!is_visible_file(conn, dirname, dname, &st, True)) {
+ continue;
+ }
+
+ DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
+ status = NT_STATUS_DIRECTORY_NOT_EMPTY;
+ break;
+ }
+ CloseDir(dir_hnd);
+
+ return status;
+}
diff --git a/source/smbd/dmapi.c b/source/smbd/dmapi.c
index a9d83c782bb..b8c23c2dce6 100644
--- a/source/smbd/dmapi.c
+++ b/source/smbd/dmapi.c
@@ -40,6 +40,8 @@ BOOL dmapi_have_session(void) { return False; }
#include <sys/jfsdmapi.h>
#elif defined(HAVE_SYS_DMAPI_H)
#include <sys/dmapi.h>
+#elif defined(HAVE_DMAPI_H)
+#include <dmapi.h>
#endif
#define DMAPI_SESSION_NAME "samba"
@@ -240,6 +242,13 @@ uint32 dmapi_file_flags(const char * const path)
}
}
+ /* AIX has DMAPI but no POSIX capablities support. In this case,
+ * we need to be root to do DMAPI manipulations.
+ */
+#ifndef HAVE_POSIX_CAPABILITIES
+ become_root();
+#endif
+
err = dm_path_to_handle(CONST_DISCARD(char *, path),
&dm_handle, &dm_handle_len);
if (err < 0) {
@@ -247,7 +256,7 @@ uint32 dmapi_file_flags(const char * const path)
path, strerror(errno)));
if (errno != EPERM) {
- return 0;
+ goto done;
}
/* Linux capabilities are broken in that changing our
@@ -265,7 +274,7 @@ uint32 dmapi_file_flags(const char * const path)
DEBUG(DMAPI_TRACE,
("retrying dm_path_to_handle(%s): %s\n",
path, strerror(errno)));
- return 0;
+ goto done;
}
}
@@ -275,7 +284,7 @@ uint32 dmapi_file_flags(const char * const path)
DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n",
path, strerror(errno)));
dm_handle_free(dm_handle, dm_handle_len);
- return 0;
+ goto done;
}
/* We figure that the only reason a DMAPI application would be
@@ -294,6 +303,12 @@ uint32 dmapi_file_flags(const char * const path)
DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path));
}
+done:
+
+#ifndef HAVE_POSIX_CAPABILITIES
+ unbecome_root();
+#endif
+
return flags;
}
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 61145fde2f0..ad79bbacddf 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -35,14 +35,6 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
Work out whether this file is offline
****************************************************************************/
-#ifndef ISDOT
-#define ISDOT(p) (*(p) == '.' && *((p) + 1) == '\0')
-#endif /* ISDOT */
-
-#ifndef ISDOTDOT
-#define ISDOTDOT(p) (*(p) == '.' && *((p) + 1) == '.' && *((p) + 2) == '\0')
-#endif /* ISDOTDOT */
-
static uint32 set_offline_flag(connection_struct *conn, const char *const path)
{
if (ISDOT(path) || ISDOTDOT(path)) {
@@ -59,7 +51,7 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path)
/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
- if creating file and inheriting
+ if creating file and inheriting (i.e. parent_dir != NULL)
apply read/write bits from parent directory.
else
everybody gets read bit set
@@ -79,23 +71,26 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path)
}
****************************************************************************/
-mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file)
+mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
+ const char *inherit_from_dir)
{
mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
- mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */
+ mode_t dir_mode = 0; /* Mode of the inherit_from directory if
+ * inheriting. */
if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
- if (fname && creating_file && lp_inherit_perms(SNUM(conn))) {
- char *dname;
+ if (fname && (inherit_from_dir != NULL)
+ && lp_inherit_perms(SNUM(conn))) {
SMB_STRUCT_STAT sbuf;
- dname = parent_dirname(fname);
- DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
- if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) {
- DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
+ DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
+ inherit_from_dir));
+ if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
+ DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
+ inherit_from_dir, strerror(errno)));
return(0); /* *** shouldn't happen! *** */
}
@@ -300,8 +295,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
* are not violating security in doing the setxattr.
*/
- fsp = open_file_fchmod(conn,path,sbuf);
- if (!fsp)
+ if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp)))
return ret;
become_root();
if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
@@ -430,7 +424,9 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
chmod a file - but preserve some bits.
********************************************************************/
-int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file)
+int file_set_dosmode(connection_struct *conn, const char *fname,
+ uint32 dosmode, SMB_STRUCT_STAT *st,
+ const char *parent_dir)
{
SMB_STRUCT_STAT st1;
int mask=0;
@@ -463,7 +459,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
return 0;
}
- unixmode = unix_mode(conn,dosmode,fname, creating_file);
+ unixmode = unix_mode(conn,dosmode,fname, parent_dir);
/* preserve the s bits */
mask |= (S_ISUID | S_ISGID);
@@ -495,8 +491,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
- if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0)
+ if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
return 0;
+ }
if((errno != EPERM) && (errno != EACCES))
return -1;
@@ -518,13 +517,15 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
* holding. We need to review this.... may need to
* break batch oplocks open by others. JRA.
*/
- files_struct *fsp = open_file_fchmod(conn,fname,st);
- if (!fsp)
+ files_struct *fsp;
+ if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,st,&fsp)))
return -1;
become_root();
ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
unbecome_root();
close_file_fchmod(fsp);
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
return( ret );
@@ -597,6 +598,9 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
return False;
}
+
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
return(True);
}
diff --git a/source/smbd/error.c b/source/smbd/error.c
index fa236f0de05..0860b7d1d91 100644
--- a/source/smbd/error.c
+++ b/source/smbd/error.c
@@ -24,40 +24,6 @@
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 uint32 override_ERR_code;
-static NTSTATUS override_ERR_ntstatus;
-
-/****************************************************************************
- 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 set_saved_error_triple(int eclass, int ecode, NTSTATUS status)
-{
- override_ERR_class = eclass;
- override_ERR_code = ecode;
- override_ERR_ntstatus = status;
-}
-
-void set_saved_ntstatus(NTSTATUS status)
-{
- uint8 tmp_eclass; /* Hmmm. override_ERR_class is not uint8... */
- override_ERR_ntstatus = status;
- ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code);
- override_ERR_class = tmp_eclass;
-
-}
-
-/****************************************************************************
- Return the current settings of the error triple. Return True if any are set.
-****************************************************************************/
-
-NTSTATUS get_saved_ntstatus(void)
-{
- return override_ERR_ntstatus;
-}
/****************************************************************************
Create an error packet from a cached error.
@@ -103,6 +69,10 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s
return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
}
+BOOL use_nt_status(void)
+{
+ return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
+}
/****************************************************************************
Create an error packet. Normally called using the ERROR() macro.
@@ -111,24 +81,14 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_s
If the override errors are set they take precedence over any passed in values.
****************************************************************************/
-int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
{
- int outsize = set_message(outbuf,0,0,True);
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 (eclass == (uint8)-1) {
force_nt_status = True;
- } else if (NT_STATUS_IS_INVALID(ntstatus)) {
+ } else if (NT_STATUS_IS_DOS(ntstatus)) {
force_dos_status = True;
}
@@ -146,7 +106,10 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
nt_errstr(ntstatus)));
} else {
/* We're returning a DOS error only. */
- if (eclass == 0 && NT_STATUS_V(ntstatus)) {
+ if (NT_STATUS_IS_DOS(ntstatus)) {
+ eclass = NT_STATUS_DOS_CLASS(ntstatus);
+ ecode = NT_STATUS_DOS_CODE(ntstatus);
+ } else if (eclass == 0 && NT_STATUS_V(ntstatus)) {
ntstatus_to_dos(ntstatus, &eclass, &ecode);
}
@@ -161,6 +124,11 @@ int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, in
eclass,
ecode));
}
+}
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+{
+ int outsize = set_message(outbuf,0,0,True);
+ error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
return outsize;
}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index b4f1f02b724..208b3256673 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -101,24 +101,26 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname)
Open a fake quota file with a share mode.
****************************************************************************/
-files_struct *open_fake_file(connection_struct *conn,
+NTSTATUS open_fake_file(connection_struct *conn,
enum FAKE_FILE_TYPE fake_file_type,
const char *fname,
- uint32 access_mask)
+ uint32 access_mask,
+ files_struct **result)
{
files_struct *fsp = NULL;
+ NTSTATUS status;
/* access check */
if (current_user.ut.uid != 0) {
DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n",
lp_servicename(SNUM(conn)),fname,conn->user));
- errno = EACCES;
- return NULL;
+ return NT_STATUS_ACCESS_DENIED;
+
}
- fsp = file_new(conn);
- if(!fsp) {
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
}
DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n",
@@ -128,7 +130,7 @@ files_struct *open_fake_file(connection_struct *conn,
fsp->fh->fd = -1;
fsp->vuid = current_user.vuid;
fsp->fh->pos = -1;
- fsp->can_lock = True; /* Should this be true ? */
+ fsp->can_lock = False; /* Should this be true ? - No, JRA */
fsp->access_mask = access_mask;
string_set(&fsp->fsp_name,fname);
@@ -136,11 +138,12 @@ files_struct *open_fake_file(connection_struct *conn,
if (fsp->fake_file_handle==NULL) {
file_free(fsp);
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
conn->num_files_open++;
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
}
void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
@@ -157,8 +160,8 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
(*fh) = NULL;
}
-int close_fake_file(files_struct *fsp)
+NTSTATUS close_fake_file(files_struct *fsp)
{
file_free(fsp);
- return 0;
+ return NT_STATUS_OK;
}
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index 375bfbe7cf3..e0945be8893 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -214,7 +214,7 @@ ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n)
if (!fsp->can_write) {
errno = EPERM;
- return(0);
+ return -1;
}
if (!fsp->modified) {
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index 6c0f8b77585..eb86a0efd16 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -46,16 +46,49 @@ static BOOL fname_equal(const char *name1, const char *name2, BOOL case_sensitiv
Mangle the 2nd name and check if it is then equal to the first name.
****************************************************************************/
-static BOOL mangled_equal(const char *name1, const char *name2, int snum)
+static BOOL mangled_equal(const char *name1, const char *name2,
+ const struct share_params *p)
{
pstring tmpname;
pstrcpy(tmpname, name2);
- mangle_map(tmpname, True, False, snum);
+ mangle_map(tmpname, True, False, p);
return strequal(name1, tmpname);
}
/****************************************************************************
+ Cope with the differing wildcard and non-wildcard error cases.
+****************************************************************************/
+
+static NTSTATUS determine_path_error(const char *name, BOOL allow_wcard_last_component)
+{
+ const char *p;
+
+ if (!allow_wcard_last_component) {
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ /* We're terminating here so we
+ * can be a little slower and get
+ * the error code right. Windows
+ * treats the last part of the pathname
+ * separately I think, so if the last
+ * component is a wildcard then we treat
+ * this ./ as "end of component" */
+
+ p = strchr(name, '/');
+
+ if (!p && (ms_has_wild(name) || ISDOT(name))) {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ } else {
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+}
+
+/****************************************************************************
This routine is called to convert names from the dos namespace to unix
namespace. It needs to handle any case conversions, mangling, format
changes etc.
@@ -63,18 +96,20 @@ changes etc.
We assume that we have already done a chdir() to the right "root" directory
for this service.
-The function will return False if some part of the name except for the last
-part cannot be resolved
+The function will return an NTSTATUS error if some part of the name except for the last
+part cannot be resolved, else NT_STATUS_OK.
+
+Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
+get any fatal errors that should immediately terminate the calling
+SMB processing whilst resolving.
If the saved_last_component != 0, then the unmodified last component
of the pathname is returned there. This is used in an exceptional
case in reply_mv (so far). If saved_last_component == 0 then nothing
is returned there.
-The bad_path arg is set to True if the filename walk failed. This is
-used to pick the correct error code to return between ENOENT and ENOTDIR
-as Windows applications depend on ERRbadpath being returned if a component
-of a pathname does not exist.
+If last_component_wcard is true then a MS wildcard was detected and
+should be allowed in the last component of the path only.
On exit from unix_convert, if *pst was not null, then the file stat
struct will be returned if the file exists and was found, if not this
@@ -82,8 +117,11 @@ stat struct will be filled with zeros (and this can be detected by checking
for nlinks = 0, which can never be true for any file).
****************************************************************************/
-BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component,
- BOOL *bad_path, SMB_STRUCT_STAT *pst)
+NTSTATUS unix_convert(connection_struct *conn,
+ pstring name,
+ BOOL allow_wcard_last_component,
+ char *saved_last_component,
+ SMB_STRUCT_STAT *pst)
{
SMB_STRUCT_STAT st;
char *start, *end;
@@ -95,14 +133,15 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
SET_STAT_INVALID(*pst);
*dirpath = 0;
- *bad_path = False;
- if(saved_last_component)
+
+ if(saved_last_component) {
*saved_last_component = 0;
+ }
if (conn->printer) {
/* we don't ever use the filenames on a printer share as a
filename - so don't convert them */
- return True;
+ return NT_STATUS_OK;
}
DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
@@ -135,7 +174,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*pst = st;
}
DEBUG(5,("conversion finished \"\" -> %s\n",name));
- return(True);
+ return NT_STATUS_OK;
+ }
+
+ if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) {
+ /* Start of pathname can't be "." only. */
+ if (name[1] == '\0' || name[2] == '\0') {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ } else {
+ return determine_path_error(&name[2], allow_wcard_last_component);
+ }
}
/*
@@ -144,10 +192,11 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
if(saved_last_component) {
end = strrchr_m(name, '/');
- if(end)
+ if (end) {
pstrcpy(saved_last_component, end + 1);
- else
+ } else {
pstrcpy(saved_last_component, name);
+ }
}
/*
@@ -168,7 +217,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {
*pst = st;
- return True;
+ return NT_STATUS_OK;
}
/*
@@ -176,10 +225,22 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*/
if (SMB_VFS_STAT(conn,name,&st) == 0) {
+ /* Ensure we catch all names with in "/."
+ this is disallowed under Windows. */
+ const char *p = strstr(name, "/."); /* mb safe. */
+ if (p) {
+ if (p[2] == '/') {
+ /* Error code within a pathname. */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else if (p[2] == '\0') {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
stat_cache_add(orig_path, name, conn->case_sensitive);
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
*pst = st;
- return(True);
+ return NT_STATUS_OK;
}
DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
@@ -189,18 +250,20 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* sensitive then searching won't help.
*/
- if (conn->case_sensitive && !mangle_is_mangled(name, SNUM(conn)) && !*lp_mangled_map(SNUM(conn)))
- return(False);
-
- name_has_wildcard = ms_has_wild(start);
+ if (conn->case_sensitive &&
+ !mangle_is_mangled(name, conn->params) &&
+ !*lp_mangled_map(conn->params)) {
+ return NT_STATUS_OK;
+ }
/*
* is_mangled() was changed to look at an entire pathname, not
* just a component. JRA.
*/
- if (mangle_is_mangled(start, SNUM(conn)))
+ if (mangle_is_mangled(start, conn->params)) {
component_was_mangled = True;
+ }
/*
* Now we need to recursively match the name against the real
@@ -216,16 +279,43 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
/*
* Pinpoint the end of this section of the filename.
*/
- end = strchr_m(start, '/');
+ end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */
/*
* Chop the name at this point.
*/
- if (end)
+ if (end) {
*end = 0;
+ }
- if(saved_last_component != 0)
+ if (saved_last_component != 0) {
pstrcpy(saved_last_component, end ? end + 1 : start);
+ }
+
+ /* The name cannot have a component of "." */
+
+ if (ISDOT(start)) {
+ if (!end) {
+ /* Error code at the end of a pathname. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ return determine_path_error(end+1, allow_wcard_last_component);
+ }
+
+ /* The name cannot have a wildcard if it's not
+ the last component. */
+
+ name_has_wildcard = ms_has_wild(start);
+
+ /* Wildcard not valid anywhere. */
+ if (name_has_wildcard && !allow_wcard_last_component) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+
+ /* Wildcards never valid within a pathname. */
+ if (name_has_wildcard && end) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
/*
* Check if the name exists up to this point.
@@ -249,9 +339,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Windows applications depend on the difference between
* these two errors.
*/
- errno = ENOTDIR;
- *bad_path = True;
- return(False);
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
if (!end) {
@@ -276,8 +364,9 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* later.
*/
- if (end)
+ if (end) {
pstrcpy(rest,end+1);
+ }
/* Reset errno so we can detect directory open errors. */
errno = 0;
@@ -286,7 +375,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Try to find this part of the path in the directory.
*/
- if (ms_has_wild(start) ||
+ if (name_has_wildcard ||
!scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) {
if (end) {
/*
@@ -302,13 +391,24 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* Windows applications depend on the difference between
* these two errors.
*/
- *bad_path = True;
- return(False);
+
+ /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
+ in the filename walk. */
+
+ if (errno == ENOENT || errno == ENOTDIR) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ return map_nt_error_from_unix(errno);
}
- if (errno == ENOTDIR) {
- *bad_path = True;
- return(False);
+ /* ENOENT is the only valid error here. */
+ if (errno != ENOENT) {
+ /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
+ in the filename walk. */
+ if (errno == ENOTDIR) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ return map_nt_error_from_unix(errno);
}
/*
@@ -318,7 +418,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>.
*/
if (!conn->case_preserve ||
- (mangle_is_8_3(start, False, SNUM(conn)) &&
+ (mangle_is_8_3(start, False, conn->params) &&
!conn->short_case_preserve)) {
strnorm(start, lp_defaultcase(SNUM(conn)));
}
@@ -328,12 +428,12 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* base of the filename.
*/
- if (mangle_is_mangled(start, SNUM(conn))) {
- mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), SNUM(conn));
+ if (mangle_is_mangled(start, conn->params)) {
+ mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params);
}
DEBUG(5,("New file %s\n",start));
- return(True);
+ return NT_STATUS_OK;
}
/*
@@ -344,7 +444,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
end = start + strlen(start);
if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) ||
!safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) {
- return False;
+ return map_nt_error_from_unix(ENAMETOOLONG);
}
*end = '\0';
} else {
@@ -362,11 +462,18 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
}
} /* end else */
+#ifdef DEVELOPER
+ if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) {
+ return NT_STATUS_DELETE_PENDING;
+ }
+#endif
+
/*
* Add to the dirpath that we have resolved so far.
*/
- if (*dirpath)
+ if (*dirpath) {
pstrcat(dirpath,"/");
+ }
pstrcat(dirpath,start);
@@ -375,14 +482,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* as this can change the size.
*/
- if(!component_was_mangled && !name_has_wildcard)
+ if(!component_was_mangled && !name_has_wildcard) {
stat_cache_add(orig_path, dirpath, conn->case_sensitive);
+ }
/*
* Restore the / that we wiped out earlier.
*/
- if (end)
+ if (end) {
*end = '/';
+ }
}
/*
@@ -390,15 +499,16 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* as this can change the size.
*/
- if(!component_was_mangled && !name_has_wildcard)
+ if(!component_was_mangled && !name_has_wildcard) {
stat_cache_add(orig_path, name, conn->case_sensitive);
+ }
/*
* The name has been resolved.
*/
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
- return(True);
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -408,28 +518,25 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
a valid one for the user to access.
****************************************************************************/
-BOOL check_name(const pstring name,connection_struct *conn)
+NTSTATUS check_name(connection_struct *conn, const pstring name)
{
- BOOL ret = True;
-
if (IS_VETO_PATH(conn, name)) {
/* Is it not dot or dot dot. */
if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
- DEBUG(5,("file path name %s vetoed\n",name));
- errno = ENOENT;
- return False;
+ DEBUG(5,("check_name: file path name %s vetoed\n",name));
+ return map_nt_error_from_unix(ENOENT);
}
}
if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
- ret = reduce_name(conn,name);
- }
-
- if (!ret) {
- DEBUG(5,("check_name on %s failed\n",name));
+ NTSTATUS status = reduce_name(conn,name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
+ return status;
+ }
}
- return(ret);
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -444,7 +551,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
BOOL mangled;
long curpos;
- mangled = mangle_is_mangled(name, SNUM(conn));
+ mangled = mangle_is_mangled(name, conn->params);
/* handle null paths */
if (*path == 0)
@@ -466,7 +573,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
*/
if (mangled && !conn->case_sensitive) {
- mangled = !mangle_check_cache( name, maxlength, SNUM(conn));
+ mangled = !mangle_check_cache( name, maxlength, conn->params);
}
/* open the directory */
@@ -495,7 +602,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
* against unmangled name.
*/
- if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) {
+ if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) {
/* we've found the file, change it's name and return */
safe_strcpy(name, dname, maxlength);
CloseDir(cur_dir);
diff --git a/source/smbd/files.c b/source/smbd/files.c
index e020d8e13a6..66ef37bb0fa 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -59,7 +59,7 @@ static unsigned long get_gen_count(void)
Find first available file slot.
****************************************************************************/
-files_struct *file_new(connection_struct *conn)
+NTSTATUS file_new(connection_struct *conn, files_struct **result)
{
int i;
static int first_file;
@@ -82,14 +82,12 @@ files_struct *file_new(connection_struct *conn)
/* TODO: We have to unconditionally return a DOS error here,
* W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
* NTSTATUS negotiated */
- set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES);
- return NULL;
+ return NT_STATUS_TOO_MANY_OPENED_FILES;
}
fsp = SMB_MALLOC_P(files_struct);
if (!fsp) {
- set_saved_ntstatus(NT_STATUS_NO_MEMORY);
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCTP(fsp);
@@ -97,8 +95,7 @@ files_struct *file_new(connection_struct *conn)
fsp->fh = SMB_MALLOC_P(struct fd_handle);
if (!fsp->fh) {
SAFE_FREE(fsp);
- set_saved_ntstatus(NT_STATUS_NO_MEMORY);
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCTP(fsp->fh);
@@ -131,8 +128,9 @@ files_struct *file_new(connection_struct *conn)
if (fsp_fi_cache.fsp == NULL) {
ZERO_STRUCT(fsp_fi_cache);
}
-
- return fsp;
+
+ *result = fsp;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -441,6 +439,11 @@ void file_free(files_struct *fsp)
fsp->fh->ref_count--;
}
+ if (fsp->notify) {
+ notify_remove(fsp->conn->notify_ctx, fsp);
+ TALLOC_FREE(fsp->notify);
+ }
+
bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
files_used--;
@@ -464,24 +467,16 @@ void file_free(files_struct *fsp)
}
/****************************************************************************
- Get a fsp from a packet given the offset of a 16 bit fnum.
+ Get an fsp from a 16 bit fnum.
****************************************************************************/
-files_struct *file_fsp(char *buf, int where)
+files_struct *file_fnum(uint16 fnum)
{
- int fnum, count=0;
files_struct *fsp;
-
- if (chain_fsp)
- return chain_fsp;
-
- if (!buf)
- return NULL;
- fnum = SVAL(buf, where);
+ int count=0;
for (fsp=Files;fsp;fsp=fsp->next, count++) {
if (fsp->fnum == fnum) {
- chain_fsp = fsp;
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}
@@ -492,6 +487,29 @@ files_struct *file_fsp(char *buf, int where)
}
/****************************************************************************
+ Get an fsp from a packet given the offset of a 16 bit fnum.
+****************************************************************************/
+
+files_struct *file_fsp(char *buf, int where)
+{
+ files_struct *fsp;
+
+ if (chain_fsp) {
+ return chain_fsp;
+ }
+
+ if (!buf) {
+ return NULL;
+ }
+
+ fsp = file_fnum(SVAL(buf, where));
+ if (fsp) {
+ chain_fsp = fsp;
+ }
+ return fsp;
+}
+
+/****************************************************************************
Reset the chained fsp - done at the start of a packet reply.
****************************************************************************/
@@ -504,15 +522,19 @@ void file_chain_reset(void)
Duplicate the file handle part for a DOS or FCB open.
****************************************************************************/
-files_struct *dup_file_fsp(files_struct *fsp,
+NTSTATUS dup_file_fsp(files_struct *fsp,
uint32 access_mask,
uint32 share_access,
- uint32 create_options)
+ uint32 create_options,
+ files_struct **result)
{
- files_struct *dup_fsp = file_new(fsp->conn);
+ NTSTATUS status;
+ files_struct *dup_fsp;
- if (!dup_fsp) {
- return NULL;
+ status = file_new(fsp->conn, &dup_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
SAFE_FREE(dup_fsp->fh);
@@ -547,5 +569,6 @@ files_struct *dup_file_fsp(files_struct *fsp,
dup_fsp->aio_write_behind = fsp->aio_write_behind;
string_set(&dup_fsp->fsp_name,fsp->fsp_name);
- return dup_fsp;
+ *result = dup_fsp;
+ return NT_STATUS_OK;
}
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index e6dfc6506a0..ca128d29d9c 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -115,7 +115,7 @@ void send_trans_reply(char *outbuf,
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans_reply: send_smb failed.");
+ exit_server_cleanly("send_trans_reply: send_smb failed.");
tot_data_sent = this_ldata;
tot_param_sent = this_lparam;
@@ -149,7 +149,7 @@ void send_trans_reply(char *outbuf,
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans_reply: send_smb failed.");
+ exit_server_cleanly("send_trans_reply: send_smb failed.");
tot_data_sent += this_ldata;
tot_param_sent += this_lparam;
@@ -447,7 +447,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_NT(result);
}
- if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
DEBUG(0, ("talloc failed\n"));
END_PROFILE(SMBtrans);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -458,6 +458,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
state->mid = SVAL(inbuf, smb_mid);
state->vuid = SVAL(inbuf, smb_uid);
state->setup_count = CVAL(inbuf, smb_suwcnt);
+ state->setup = NULL;
state->total_param = SVAL(inbuf, smb_tpscnt);
state->param = NULL;
state->total_data = SVAL(inbuf, smb_tdscnt);
@@ -478,7 +479,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_data) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- state->data = SMB_MALLOC(state->total_data);
+ state->data = (char *)SMB_MALLOC(state->total_data);
if (state->data == NULL) {
DEBUG(0,("reply_trans: data malloc fail for %u "
"bytes !\n", (unsigned int)state->total_data));
@@ -498,7 +499,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_param) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- state->param = SMB_MALLOC(state->total_param);
+ state->param = (char *)SMB_MALLOC(state->total_param);
if (state->param == NULL) {
DEBUG(0,("reply_trans: param malloc fail for %u "
"bytes !\n", (unsigned int)state->total_param));
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index d94572bc767..8ecc965c0d3 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -72,7 +72,11 @@ static int CopyExpanded(connection_struct *conn,
StrnCpy(buf,src,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf,sizeof(buf));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ buf, sizeof(buf));
l = push_ascii(*dst,buf,*n, STR_TERMINATE);
(*dst) += l;
(*n) -= l;
@@ -99,7 +103,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
}
StrnCpy(buf,s,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf,sizeof(buf));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ buf, sizeof(buf));
return strlen(buf) + 1;
}
@@ -111,7 +119,11 @@ static char *Expand(connection_struct *conn, int snum, char *s)
}
StrnCpy(buf,s,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf,sizeof(buf));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ buf, sizeof(buf));
return &buf[0];
}
@@ -593,7 +605,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
- standard_sub_basic( "", location, sizeof(location)-1 );
+ standard_sub_basic( "", "", location, sizeof(location)-1 );
PACKS(desc,"z", location); /* share to retrieve files */
PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
@@ -1965,7 +1977,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
size_t i;
NTSTATUS result;
DOM_SID user_sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
TALLOC_CTX *mem_ctx;
*rparam_len = 8;
@@ -2530,7 +2542,6 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
uint32 jobid;
- int snum;
fstring sharename;
int uLevel = SVAL(p,2);
int function = SVAL(p,4);
@@ -2544,9 +2555,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
return False;
}
- if ( (snum = lp_servicenumber(sharename)) == -1 ) {
- DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
- sharename));
+ if (!share_defined(sharename)) {
+ DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
+ sharename));
return False;
}
@@ -2569,14 +2580,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
/* change job place in the queue,
data gives the new place */
place = SVAL(data,0);
- if (print_job_set_place(snum, jobid, place)) {
+ if (print_job_set_place(sharename, jobid, place)) {
errcode=NERR_Success;
}
break;
case 0xb:
/* change print job name, data gives the name */
- if (print_job_set_name(snum, jobid, data)) {
+ if (print_job_set_name(sharename, jobid, data)) {
errcode=NERR_Success;
}
break;
@@ -2666,7 +2677,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
p = *rdata;
p2 = p + struct_len;
if (uLevel != 20) {
- srvstr_push(NULL, p,get_local_machine_name(),16,
+ srvstr_push(NULL, p,global_myname(),16,
STR_ASCII|STR_UPPER|STR_TERMINATE);
}
p += 16;
@@ -2680,7 +2691,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
for (i=0;i<count;i++) {
- if (strequal(servers[i].name,get_local_machine_name())) {
+ if (strequal(servers[i].name,global_myname())) {
servertype = servers[i].type;
push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
}
@@ -2697,7 +2708,11 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
SIVAL(p,6,0);
} else {
SIVAL(p,6,PTR_DIFF(p2,*rdata));
- standard_sub_conn(conn,comment,sizeof(comment));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ comment, sizeof(comment));
StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
p2 = skip_string(p2,1);
}
@@ -3122,8 +3137,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVALS(p,102,-1); /* bad_pw_count */
SSVALS(p,104,-1); /* num_logons */
SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
- pstrcpy(p2,"\\\\%L");
- standard_sub_conn(conn, p2,0);
+ {
+ pstring tmp;
+ pstrcpy(tmp, "\\\\%L");
+ standard_sub_basic("", "", tmp, sizeof(tmp));
+ pstrcpy(p2, tmp);
+ }
p2 = skip_string(p2,1);
SSVAL(p,110,49); /* country_code */
SSVAL(p,112,860); /* code page */
diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c
index ed69a6210e8..16f99636eb5 100644
--- a/source/smbd/mangle.c
+++ b/source/smbd/mangle.c
@@ -81,22 +81,24 @@ void mangle_change_to_posix(void)
/*
see if a filename has come out of our mangling code
*/
-BOOL mangle_is_mangled(const char *s, int snum)
+BOOL mangle_is_mangled(const char *s, const struct share_params *p)
{
- return mangle_fns->is_mangled(s, snum);
+ return mangle_fns->is_mangled(s, p);
}
/*
see if a filename matches the rules of a 8.3 filename
*/
-BOOL mangle_is_8_3(const char *fname, BOOL check_case, int snum)
+BOOL mangle_is_8_3(const char *fname, BOOL check_case,
+ const struct share_params *p)
{
- return mangle_fns->is_8_3(fname, check_case, False, snum);
+ return mangle_fns->is_8_3(fname, check_case, False, p);
}
-BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum)
+BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case,
+ const struct share_params *p)
{
- return mangle_fns->is_8_3(fname, check_case, True, snum);
+ return mangle_fns->is_8_3(fname, check_case, True, p);
}
/*
@@ -105,20 +107,22 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case, int snum)
looking for a matching name if it doesn't. It should succeed most of the time
or there will be a huge performance penalty
*/
-BOOL mangle_check_cache(char *s, size_t maxlen, int snum)
+BOOL mangle_check_cache(char *s, size_t maxlen,
+ const struct share_params *p)
{
- return mangle_fns->check_cache(s, maxlen, snum);
+ return mangle_fns->check_cache(s, maxlen, p);
}
/*
map a long filename to a 8.3 name.
*/
-void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum)
+void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
+ const struct share_params *p)
{
/* name mangling can be disabled for speed, in which case
we just truncate the string */
- if (!lp_manglednames(snum)) {
+ if (!lp_manglednames(p)) {
if (need83) {
string_truncate(OutName, 12);
}
@@ -126,6 +130,6 @@ void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum)
}
/* invoke the inane "mangled map" code */
- mangle_map_filename(OutName, snum);
- mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum), snum);
+ mangle_map_filename(OutName, p);
+ mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
}
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 2092f430c07..320e31ab679 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -275,14 +275,15 @@ done:
return ret;
}
-static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
+ const struct share_params *p)
{
const char *f;
smb_ucs2_t *ucs2name;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
size_t size;
- magic_char = lp_magicchar(snum);
+ magic_char = lp_magicchar(p);
if (!fname || !*fname)
return False;
@@ -360,11 +361,11 @@ static void init_chartest( void )
*
* ************************************************************************** **
*/
-static BOOL is_mangled(const char *s, int snum)
+static BOOL is_mangled(const char *s, const struct share_params *p)
{
char *magic;
- magic_char = lp_magicchar(snum);
+ magic_char = lp_magicchar(p);
if( !ct_initialized )
init_chartest();
@@ -460,13 +461,13 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name )
* ************************************************************************** **
*/
-static BOOL check_cache( char *s, size_t maxlen, int snum )
+static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
{
TDB_DATA data_val;
char *ext_start = NULL;
char *saved_ext = NULL;
- magic_char = lp_magicchar(snum);
+ magic_char = lp_magicchar(p);
/* If the cache isn't initialized, give up. */
if( !tdb_mangled_cache )
@@ -606,10 +607,11 @@ static void to_8_3(char *s, int default_case)
* ****************************************************************************
*/
-static void name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum)
+static void name_map(char *OutName, BOOL need83, BOOL cache83,
+ int default_case, const struct share_params *p)
{
smb_ucs2_t *OutName_ucs2;
- magic_char = lp_magicchar(snum);
+ magic_char = lp_magicchar(p);
DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
need83 ? "True" : "False", cache83 ? "True" : "False"));
diff --git a/source/smbd/mangle_hash2.c b/source/smbd/mangle_hash2.c
index 0a161c9e769..a39f49ec796 100644
--- a/source/smbd/mangle_hash2.c
+++ b/source/smbd/mangle_hash2.c
@@ -101,7 +101,7 @@ static unsigned mangle_prefix;
hashing the resulting cache entry to match the known hash
*/
static char **prefix_cache;
-static u32 *prefix_cache_hashes;
+static unsigned int *prefix_cache_hashes;
/* these are the characters we use in the 8.3 hash. Must be 36 chars long */
static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -119,10 +119,10 @@ static const char *reserved_names[] =
this hash needs to be fast with a low collision rate (what hash doesn't?)
*/
-static u32 mangle_hash(const char *key, unsigned int length)
+static unsigned int mangle_hash(const char *key, unsigned int length)
{
- u32 value;
- u32 i;
+ unsigned int value;
+ unsigned int i;
fstring str;
/* we have to uppercase here to ensure that the mangled name
@@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length)
/* Set the initial value from the key size. */
for (value = FNV1_INIT, i=0; i < length; i++) {
- value *= (u32)FNV1_PRIME;
- value ^= (u32)(str[i]);
+ value *= (unsigned int)FNV1_PRIME;
+ value ^= (unsigned int)(str[i]);
}
/* note that we force it to a 31 bit hash, to keep within the limits
@@ -162,7 +162,7 @@ static BOOL cache_init(void)
return False;
}
- prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE);
+ prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE);
if (!prefix_cache_hashes) {
return False;
}
@@ -173,7 +173,7 @@ static BOOL cache_init(void)
/*
insert an entry into the prefix cache. The string might not be null
terminated */
-static void cache_insert(const char *prefix, int length, u32 hash)
+static void cache_insert(const char *prefix, int length, unsigned int hash)
{
int i = hash % MANGLE_CACHE_SIZE;
@@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash)
/*
lookup an entry in the prefix cache. Return NULL if not found.
*/
-static const char *cache_lookup(u32 hash)
+static const char *cache_lookup(unsigned int hash)
{
int i = hash % MANGLE_CACHE_SIZE;
@@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
directory separators. It should return true if any component is
mangled
*/
-static BOOL is_mangled(const char *name, int snum)
+static BOOL is_mangled(const char *name, const struct share_params *parm)
{
const char *p;
const char *s;
@@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, int snum)
simplifies things greatly (it means that we know the string won't
get larger when converted from UNIX to DOS formats)
*/
-static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
{
int len, i;
char *dot_p;
@@ -370,15 +370,15 @@ static void mangle_reset(void)
try to find a 8.3 name in the cache, and if found then
replace the string with the original long name.
*/
-static BOOL check_cache(char *name, size_t maxlen, int snum)
+static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
{
- u32 hash, multiplier;
+ unsigned int hash, multiplier;
unsigned int i;
const char *prefix;
char extension[4];
/* make sure that this is a mangled name from this cache */
- if (!is_mangled(name, snum)) {
+ if (!is_mangled(name, p)) {
M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
return False;
}
@@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum)
/* we need to extract the hash from the 8.3 name */
hash = base_reverse[(unsigned char)name[7]];
for (multiplier=36, i=5;i>=mangle_prefix;i--) {
- u32 v = base_reverse[(unsigned char)name[i]];
+ unsigned int v = base_reverse[(unsigned char)name[i]];
hash += multiplier * v;
multiplier *= 36;
}
@@ -465,7 +465,7 @@ static BOOL is_legal_name(const char *name)
* for mb UNIX asian characters like Japanese (SJIS) here.
* JRA.
*/
- if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) {
+ if (convert_string(CH_UNIX, CH_UTF16LE, name, 2, mbc, 2, False) == 2) {
/* Was a good mb string. */
name += 2;
continue;
@@ -510,21 +510,21 @@ static BOOL is_legal_name(const char *name)
the name parameter must be able to hold 13 bytes
*/
-static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum)
+static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
{
char *dot_p;
char lead_chars[7];
char extension[4];
unsigned int extension_length, i;
unsigned int prefix_len;
- u32 hash, v;
+ unsigned int hash, v;
char new_name[13];
/* reserved names are handled specially */
if (!is_reserved_name(name)) {
/* if the name is already a valid 8.3 name then we don't need to
do anything */
- if (is_8_3(name, False, False, snum)) {
+ if (is_8_3(name, False, False, p)) {
return;
}
@@ -724,22 +724,22 @@ struct mangle_fns *mangle_hash2_init(void)
static void posix_mangle_reset(void)
{;}
-static BOOL posix_is_mangled(const char *s, int snum)
+static BOOL posix_is_mangled(const char *s, const struct share_params *p)
{
return False;
}
-static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum)
+static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
{
return False;
}
-static BOOL posix_check_cache( char *s, size_t maxlen, int snum )
+static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p )
{
return False;
}
-static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum)
+static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
{
if (need83) {
memset(OutName, '\0', 13);
diff --git a/source/smbd/mangle_map.c b/source/smbd/mangle_map.c
index 9e798fd41b4..c5803786ec0 100644
--- a/source/smbd/mangle_map.c
+++ b/source/smbd/mangle_map.c
@@ -201,11 +201,11 @@ static void mangled_map(char *s, const char *MangledMap)
front end routine to the mangled map code
personally I think that the whole idea of "mangled map" is completely bogus
*/
-void mangle_map_filename(fstring fname, int snum)
+void mangle_map_filename(fstring fname, const struct share_params *p)
{
char *map;
- map = lp_mangled_map(snum);
+ map = lp_mangled_map(p);
if (!map || !*map) return;
mangled_map(fname, map);
diff --git a/source/smbd/message.c b/source/smbd/message.c
index 31dab458443..fd53e60c141 100644
--- a/source/smbd/message.c
+++ b/source/smbd/message.c
@@ -101,7 +101,8 @@ static void msg_deliver(void)
pstrcpy(s,lp_msg_command());
pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom)));
pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto)));
- standard_sub_basic(current_user_info.smb_name, s, sizeof(s));
+ standard_sub_basic(current_user_info.smb_name,
+ current_user_info.domain, s, sizeof(s));
pstring_sub(s,"%s",name);
smbrun(s,NULL);
}
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 1ea19f657bf..2a19d6fb418 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -30,7 +30,7 @@ extern uint32 global_client_caps;
into the dfs_path structure
**********************************************************************/
-static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp)
+static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp)
{
pstring pathname_local;
char *p, *temp;
@@ -73,26 +73,32 @@ static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp)
}
/**********************************************************************
- Parse the pathname of the form /hostname/service/reqpath
- into the dfs_path structure
+ Parse the pathname of the form /hostname/service/reqpath
+ into the dfs_path structure
+ This code is dependent on the fact that check_path_syntax() will
+ convert '\\' characters to '/'.
+ When POSIX pathnames have been selected this doesn't happen, so we
+ must look for the unaltered separator of '\\' instead of the modified '/'.
+ JRA.
**********************************************************************/
static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards)
{
pstring pathname_local;
char *p,*temp;
+ const char sepchar = lp_posix_pathnames() ? '\\' : '/';
pstrcpy(pathname_local,pathname);
p = temp = pathname_local;
ZERO_STRUCTP(pdp);
- trim_char(temp,'/','/');
+ trim_char(temp,sepchar,sepchar);
DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp));
/* now tokenize */
/* parse out hostname */
- p = strchr_m(temp,'/');
+ p = strchr_m(temp,sepchar);
if(p == NULL) {
return False;
}
@@ -102,7 +108,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL
/* parse out servicename */
temp = p+1;
- p = strchr_m(temp,'/');
+ p = strchr_m(temp,sepchar);
if(p == NULL) {
pstrcpy(pdp->servicename,temp);
pdp->reqpath[0] = '\0';
@@ -135,7 +141,6 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
ZERO_STRUCTP(conn);
- conn->service = snum;
pstrcpy(connpath, path);
pstring_sub(connpath , "%S", lp_servicename(snum));
@@ -145,6 +150,13 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
DEBUG(0,("talloc_init(connection_struct) failed!\n"));
return False;
}
+
+ if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) {
+ DEBUG(0, ("TALLOC failed\n"));
+ return False;
+ }
+
+ conn->params->service = snum;
set_conn_connectpath(conn, connpath);
@@ -249,7 +261,7 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist
talloc CTX can be NULL here if reflistp and refcnt pointers are null.
**********************************************************************/
-BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, char *path,
+BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path,
struct referral **reflistp, int *refcnt,
SMB_STRUCT_STAT *sbufp)
{
@@ -305,16 +317,21 @@ TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp
are also NULL.
*****************************************************************/
-static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *dp,
- connection_struct *conn, BOOL search_flag,
- struct referral **reflistpp, int *refcntp,
- BOOL *self_referralp, int *consumedcntp)
+static BOOL resolve_dfs_path(TALLOC_CTX *ctx,
+ const char *dfspath,
+ struct dfs_path *dp,
+ connection_struct *conn,
+ BOOL search_flag,
+ struct referral **reflistpp,
+ int *refcntp,
+ BOOL *self_referralp,
+ int *consumedcntp)
{
pstring localpath;
int consumed_level = 1;
char *p;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
pstring reqpath;
if (!dp || !conn) {
@@ -336,10 +353,25 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *
DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath));
- unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf);
- /* JRA... should we strlower the last component here.... ? */
+ /*
+ * Note the unix path conversion here we're doing we can
+ * throw away. We're looking for a symlink for a dfs
+ * resolution, if we don't find it we'll do another
+ * unix_convert later in the codepath.
+ * If we needed to remember what we'd resolved in
+ * dp->reqpath (as the original code did) we'd
+ * pstrcpy(localhost, dp->reqpath) on any code
+ * path below that returns True - but I don't
+ * think this is needed. JRA.
+ */
+
pstrcpy(localpath, dp->reqpath);
+ status = unix_convert(conn, localpath, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+
/* check if need to redirect */
if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) {
if ( search_flag ) {
@@ -356,7 +388,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *
}
/* redirect if any component in the path is a link */
- pstrcpy(reqpath, dp->reqpath);
+ pstrcpy(reqpath, localpath);
p = strrchr_m(reqpath, '/');
while (p) {
*p = '\0';
@@ -433,9 +465,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_
return True;
} else {
DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname));
-
+
/* Form non-dfs tcon-relative path */
pstrcpy(pathname, dp.reqpath);
+
DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname));
return False;
}
@@ -447,7 +480,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_
Return a self referral.
**********************************************************************/
-static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn,
+static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
int *consumedcntp, BOOL *self_referralp)
{
struct referral *ref;
@@ -478,7 +511,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn,
junction_map structure.
**********************************************************************/
-BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn,
+BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
int *consumedcntp, BOOL *self_referralp)
{
struct dfs_path dp;
@@ -640,7 +673,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
/* add the unexplained 0x16 bytes */
reply_size += 0x16;
- pdata = SMB_REALLOC(pdata,reply_size);
+ pdata = (char *)SMB_REALLOC(pdata,reply_size);
if(pdata == NULL) {
DEBUG(0,("malloc failed for Realloc!\n"));
return -1;
@@ -725,7 +758,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2;
}
- pdata = SMB_REALLOC(pdata,reply_size);
+ pdata = (char *)SMB_REALLOC(pdata,reply_size);
if(pdata == NULL) {
DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n"));
return -1;
@@ -832,9 +865,13 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref
/* create the referral depeding on version */
DEBUG(10,("max_referral_level :%d\n",max_referral_level));
- if(max_referral_level<2 || max_referral_level>3) {
+
+ if (max_referral_level < 2) {
max_referral_level = 2;
}
+ if (max_referral_level > 3) {
+ max_referral_level = 3;
+ }
switch(max_referral_level) {
case 2:
@@ -868,7 +905,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)
+BOOL create_junction(const char *pathname, struct junction_map *jucn)
{
struct dfs_path dp;
@@ -1053,6 +1090,7 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
ref->ttl = REFERRAL_TTL;
if (*lp_msdfs_proxy(snum) != '\0') {
pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum));
+ cnt++;
goto out;
}
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 3347008cdf8..fb5610b20bb 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -33,7 +33,8 @@ static void get_challenge(char buff[8])
NTSTATUS nt_status;
const uint8 *cryptkey;
- /* We might be called more than once, muliple negprots are premitted */
+ /* We might be called more than once, multiple negprots are
+ * permitted */
if (negprot_global_auth_context) {
DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
(negprot_global_auth_context->free)(&negprot_global_auth_context);
@@ -168,22 +169,24 @@ static int reply_lanman2(char *inbuf, char *outbuf)
Generate the spnego negprot reply blob. Return the number of bytes used.
****************************************************************************/
-static int negprot_spnego(char *p, uint8 *pkeylen)
+static DATA_BLOB negprot_spnego(void)
{
DATA_BLOB blob;
nstring dos_name;
fstring unix_name;
+#ifdef DEVELOPER
+ size_t slen;
+#endif
char guid[17];
const char *OIDs_krb5[] = {OID_KERBEROS5,
OID_KERBEROS5_OLD,
OID_NTLMSSP,
NULL};
const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
- int len;
global_spnego_negotiated = True;
- ZERO_STRUCT(guid);
+ memset(guid, '\0', sizeof(guid));
safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
strlower_m(unix_name);
@@ -191,11 +194,10 @@ static int negprot_spnego(char *p, uint8 *pkeylen)
safe_strcpy(guid, dos_name, sizeof(guid)-1);
#ifdef DEVELOPER
- /* valgrind fixer... */
- {
- size_t sl = strlen(guid);
- if (sizeof(guid)-sl)
- memset(&guid[sl], '\0', sizeof(guid)-sl);
+ /* Fix valgrind 'uninitialized bytes' issue. */
+ slen = strlen(dos_name);
+ if (slen < sizeof(guid)) {
+ memset(guid+slen, '\0', sizeof(guid) - slen);
}
#endif
@@ -230,20 +232,7 @@ static int negprot_spnego(char *p, uint8 *pkeylen)
SAFE_FREE(host_princ_s);
}
- memcpy(p, blob.data, blob.length);
- len = blob.length;
- if (len > 256) {
- DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
- len = 255;
- }
- data_blob_free(&blob);
-
- if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
- *pkeylen = 0;
- } else {
- *pkeylen = len;
- }
- return len;
+ return blob;
}
/****************************************************************************
@@ -263,6 +252,16 @@ static int reply_nt1(char *inbuf, char *outbuf)
global_encrypted_passwords_negotiated = lp_encrypted_passwords();
+ /* Check the flags field to see if this is Vista.
+ WinXP sets it and Vista does not. But we have to
+ distinguish from NT which doesn't set it either. */
+
+ if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
+ ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) )
+ {
+ set_remote_arch( RA_VISTA );
+ }
+
/* do spnego in user level security if the client
supports it and we can do encrypted passwords */
@@ -315,7 +314,7 @@ static int reply_nt1(char *inbuf, char *outbuf)
} else {
DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
if (lp_server_signing() == Required) {
- exit_server("reply_nt1: smb signing required and share level security selected.");
+ exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
}
}
}
@@ -349,11 +348,17 @@ static int reply_nt1(char *inbuf, char *outbuf)
STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
DEBUG(3,("not using SPNEGO\n"));
} else {
- uint8 keylen;
- int len = negprot_spnego(p, &keylen);
-
- SCVAL(outbuf,smb_vwv16+1,keylen);
- p += len;
+ DATA_BLOB spnego_blob = negprot_spnego();
+
+ if (spnego_blob.data == NULL) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ memcpy(p, spnego_blob.data, spnego_blob.length);
+ p += spnego_blob.length;
+ data_blob_free(&spnego_blob);
+
+ SCVAL(outbuf,smb_vwv16+1, 0);
DEBUG(3,("using SPNEGO\n"));
}
@@ -393,6 +398,15 @@ protocol [LM1.2X002]
protocol [LANMAN2.1]
protocol [NT LM 0.12]
+Vista:
+protocol [PC NETWORK PROGRAM 1.0]
+protocol [LANMAN1.0]
+protocol [Windows for Workgroups 3.1a]
+protocol [LM1.2X002]
+protocol [LANMAN2.1]
+protocol [NT LM 0.12]
+protocol [SMB 2.001]
+
OS/2:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
@@ -406,18 +420,19 @@ protocol [LANMAN2.1]
*
* This appears to be the matrix of which protocol is used by which
* MS product.
- Protocol WfWg Win95 WinNT Win2K OS/2
- PC NETWORK PROGRAM 1.0 1 1 1 1 1
+ Protocol WfWg Win95 WinNT Win2K OS/2 Vista
+ PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
XENIX CORE 2 2
MICROSOFT NETWORKS 3.0 2 2
DOS LM1.2X002 3 3
MICROSOFT NETWORKS 1.03 3
DOS LANMAN2.1 4 4
- LANMAN1.0 4 2 3
- Windows for Workgroups 3.1a 5 5 5 3
- LM1.2X002 6 4 4
- LANMAN2.1 7 5 5
- NT LM 0.12 6 8 6
+ LANMAN1.0 4 2 3 2
+ Windows for Workgroups 3.1a 5 5 5 3 3
+ LM1.2X002 6 4 4 4
+ LANMAN2.1 7 5 5 5
+ NT LM 0.12 6 8 6 6
+ SMB 2.001 7
*
* tim@fsg.com 09/29/95
* Win2K added by matty 17/7/99
@@ -430,6 +445,7 @@ protocol [LANMAN2.1]
#define ARCH_OS2 0x14 /* Again OS/2 is like NT */
#define ARCH_SAMBA 0x20
#define ARCH_CIFSFS 0x40
+#define ARCH_VISTA 0x8C /* Vista is like XP/2K */
#define ARCH_ALL 0x7F
@@ -477,7 +493,7 @@ int reply_negprot(connection_struct *conn,
if (done_negprot) {
END_PROFILE(SMBnegprot);
- exit_server("multiple negprot's are not permitted");
+ exit_server_cleanly("multiple negprot's are not permitted");
}
done_negprot = True;
@@ -493,6 +509,8 @@ int reply_negprot(connection_struct *conn,
arch &= ( ARCH_WFWG | ARCH_WIN95 );
else if (strcsequal(p,"NT LM 0.12"))
arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
+ else if (strcsequal(p,"SMB 2.001"))
+ arch = ARCH_VISTA;
else if (strcsequal(p,"LANMAN2.1"))
arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
else if (strcsequal(p,"LM1.2X002"))
@@ -537,7 +555,13 @@ int reply_negprot(connection_struct *conn,
set_remote_arch(RA_WINNT);
break;
case ARCH_WIN2K:
- set_remote_arch(RA_WIN2K);
+ /* Vista may have been set in the negprot so don't
+ override it here */
+ if ( get_remote_arch() != RA_VISTA )
+ set_remote_arch(RA_WIN2K);
+ break;
+ case ARCH_VISTA:
+ set_remote_arch(RA_VISTA);
break;
case ARCH_OS2:
set_remote_arch(RA_OS2);
@@ -586,7 +610,8 @@ int reply_negprot(connection_struct *conn,
DEBUG( 5, ( "negprot index=%d\n", choice ) );
if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
- exit_server("SMB signing is required and client negotiated a downlevel protocol");
+ exit_server_cleanly("SMB signing is required and "
+ "client negotiated a downlevel protocol");
}
END_PROFILE(SMBnegprot);
diff --git a/source/smbd/notify.c b/source/smbd/notify.c
index 829ca3a736d..cf60720bc74 100644
--- a/source/smbd/notify.c
+++ b/source/smbd/notify.c
@@ -3,6 +3,7 @@
change notify handling
Copyright (C) Andrew Tridgell 2000
Copyright (C) Jeremy Allison 1994-1998
+ Copyright (C) Volker Lendecke 2007
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,36 +22,95 @@
#include "includes.h"
-static struct cnotify_fns *cnotify;
+struct notify_change_request {
+ struct notify_change_request *prev, *next;
+ struct files_struct *fsp; /* backpointer for cancel by mid */
+ char request_buf[smb_size];
+ uint32 filter;
+ uint32 max_param_count;
+ uint32 current_bufsize;
+ struct notify_mid_map *mid_map;
+ void *backend_data;
+};
-/****************************************************************************
- This is the structure to queue to implement NT change
- notify. It consists of smb_size bytes stored from the
- transact command (to keep the mid, tid etc around).
- Plus the fid to examine and notify private data.
-*****************************************************************************/
+static void notify_fsp(files_struct *fsp, uint32 action, const char *name);
-struct change_notify {
- struct change_notify *next, *prev;
- files_struct *fsp;
- connection_struct *conn;
- uint32 flags;
- char request_buf[smb_size];
- void *change_data;
+static struct notify_mid_map *notify_changes_by_mid;
+
+/*
+ * For NTCancel, we need to find the notify_change_request indexed by
+ * mid. Separate list here.
+ */
+
+struct notify_mid_map {
+ struct notify_mid_map *prev, *next;
+ struct notify_change_request *req;
+ uint16 mid;
};
-static struct change_notify *change_notify_list;
+static BOOL notify_marshall_changes(int num_changes,
+ struct notify_change *changes,
+ prs_struct *ps)
+{
+ int i;
+ UNISTR uni_name;
+
+ for (i=0; i<num_changes; i++) {
+ struct notify_change *c = &changes[i];
+ size_t namelen;
+ uint32 u32_tmp; /* Temp arg to prs_uint32 to avoid
+ * signed/unsigned issues */
+
+ namelen = convert_string_allocate(
+ NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1,
+ &uni_name.buffer, True);
+ if ((namelen == -1) || (uni_name.buffer == NULL)) {
+ goto fail;
+ }
+
+ namelen -= 2; /* Dump NULL termination */
+
+ /*
+ * Offset to next entry, only if there is one
+ */
+
+ u32_tmp = (i == num_changes-1) ? 0 : namelen + 12;
+ if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail;
+
+ u32_tmp = c->action;
+ if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail;
+
+ u32_tmp = namelen;
+ if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail;
+
+ if (!prs_unistr("name", ps, 1, &uni_name)) goto fail;
+
+ /*
+ * Not NULL terminated, decrease by the 2 UCS2 \0 chars
+ */
+ prs_set_offset(ps, prs_offset(ps)-2);
+
+ SAFE_FREE(uni_name.buffer);
+ }
+
+ return True;
+
+ fail:
+ SAFE_FREE(uni_name.buffer);
+ return False;
+}
/****************************************************************************
Setup the common parts of the return packet and send it.
*****************************************************************************/
-static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code)
+static void change_notify_reply_packet(const char *request_buf,
+ NTSTATUS error_code)
{
char outbuf[smb_size+38];
memset(outbuf, '\0', sizeof(outbuf));
- construct_reply_common(inbuf, outbuf);
+ construct_reply_common(request_buf, outbuf);
ERROR_NT(error_code);
@@ -62,193 +122,363 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code)
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server_cleanly("change_notify_reply_packet: send_smb "
+ "failed.");
+}
+
+void change_notify_reply(const char *request_buf, uint32 max_param_count,
+ struct notify_change_buf *notify_buf)
+{
+ char *outbuf = NULL;
+ prs_struct ps;
+ size_t buflen = smb_size+38+max_param_count;
+
+ if (notify_buf->num_changes == -1) {
+ change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ return;
+ }
+
+ if (!prs_init(&ps, 0, NULL, False)
+ || !notify_marshall_changes(notify_buf->num_changes,
+ notify_buf->changes, &ps)) {
+ change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (prs_offset(&ps) > max_param_count) {
+ /*
+ * We exceed what the client is willing to accept. Send
+ * nothing.
+ */
+ change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ goto done;
+ }
+
+ if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
+ change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ construct_reply_common(request_buf, outbuf);
+
+ if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
+ prs_offset(&ps), NULL, 0) == -1) {
exit_server("change_notify_reply_packet: send_smb failed.");
+ }
+
+ done:
+ SAFE_FREE(outbuf);
+ prs_mem_free(&ps);
+
+ TALLOC_FREE(notify_buf->changes);
+ notify_buf->num_changes = 0;
}
-/****************************************************************************
- Remove an entry from the list and free it, also closing any
- directory handle if necessary.
-*****************************************************************************/
+static void notify_callback(void *private_data, const struct notify_event *e)
+{
+ files_struct *fsp = (files_struct *)private_data;
+ DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name));
+ notify_fsp(fsp, e->action, e->path);
+}
-static void change_notify_remove(struct change_notify *cnbp)
+NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
+ BOOL recursive)
{
- cnotify->remove_notify(cnbp->change_data);
- DLIST_REMOVE(change_notify_list, cnbp);
- ZERO_STRUCTP(cnbp);
- SAFE_FREE(cnbp);
+ char *fullpath;
+ struct notify_entry e;
+ NTSTATUS status;
+
+ SMB_ASSERT(fsp->notify == NULL);
+
+ if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_change_buf))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath,
+ fsp->fsp_name) == -1) {
+ DEBUG(0, ("asprintf failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ e.path = fullpath;
+ e.filter = filter;
+ e.subdir_filter = 0;
+ if (recursive) {
+ e.subdir_filter = filter;
+ }
+
+ status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, fsp);
+ SAFE_FREE(fullpath);
+
+ return status;
}
-/****************************************************************************
- Delete entries by fnum from the change notify pending queue.
-*****************************************************************************/
+NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
+ uint32 filter, BOOL recursive,
+ struct files_struct *fsp)
+{
+ struct notify_change_request *request = NULL;
+ struct notify_mid_map *map = NULL;
+
+ if (!(request = SMB_MALLOC_P(struct notify_change_request))
+ || !(map = SMB_MALLOC_P(struct notify_mid_map))) {
+ SAFE_FREE(request);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ request->mid_map = map;
+ map->req = request;
-void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status)
+ memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
+ request->max_param_count = max_param_count;
+ request->current_bufsize = 0;
+ request->filter = filter;
+ request->fsp = fsp;
+ request->backend_data = NULL;
+
+ DLIST_ADD_END(fsp->notify->requests, request,
+ struct notify_change_request *);
+
+ map->mid = SVAL(inbuf, smb_mid);
+ DLIST_ADD(notify_changes_by_mid, map);
+
+ /* Push the MID of this packet on the signing queue. */
+ srv_defer_sign_response(SVAL(inbuf,smb_mid));
+
+ return NT_STATUS_OK;
+}
+
+static void change_notify_remove_request(struct notify_change_request *remove_req)
{
- struct change_notify *cnbp, *next;
+ files_struct *fsp;
+ struct notify_change_request *req;
+
+ /*
+ * Paranoia checks, the fsp referenced must must have the request in
+ * its list of pending requests
+ */
+
+ fsp = remove_req->fsp;
+ SMB_ASSERT(fsp->notify != NULL);
- for (cnbp=change_notify_list; cnbp; cnbp=next) {
- next=cnbp->next;
- if (cnbp->fsp->fnum == fsp->fnum) {
- change_notify_reply_packet(cnbp->request_buf,status);
- change_notify_remove(cnbp);
+ for (req = fsp->notify->requests; req; req = req->next) {
+ if (req == remove_req) {
+ break;
}
}
+
+ if (req == NULL) {
+ smb_panic("notify_req not found in fsp's requests\n");
+ }
+
+ DLIST_REMOVE(fsp->notify->requests, req);
+ DLIST_REMOVE(notify_changes_by_mid, req->mid_map);
+ SAFE_FREE(req->mid_map);
+ TALLOC_FREE(req->backend_data);
+ SAFE_FREE(req);
}
/****************************************************************************
Delete entries by mid from the change notify pending queue. Always send reply.
*****************************************************************************/
-void remove_pending_change_notify_requests_by_mid(int mid)
+void remove_pending_change_notify_requests_by_mid(uint16 mid)
{
- struct change_notify *cnbp, *next;
+ struct notify_mid_map *map;
- for (cnbp=change_notify_list; cnbp; cnbp=next) {
- next=cnbp->next;
- if(SVAL(cnbp->request_buf,smb_mid) == mid) {
- change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED);
- change_notify_remove(cnbp);
+ for (map = notify_changes_by_mid; map; map = map->next) {
+ if (map->mid == mid) {
+ break;
}
}
+
+ if (map == NULL) {
+ return;
+ }
+
+ change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED);
+ change_notify_remove_request(map->req);
}
/****************************************************************************
- Delete entries by filename and cnum from the change notify pending queue.
- Always send reply.
+ Delete entries by fnum from the change notify pending queue.
*****************************************************************************/
-void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTATUS status)
+void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
+ NTSTATUS status)
{
- struct change_notify *cnbp, *next;
+ if (fsp->notify == NULL) {
+ return;
+ }
- for (cnbp=change_notify_list; cnbp; cnbp=next) {
- next=cnbp->next;
- /*
- * We know it refers to the same directory if the connection number and
- * the filename are identical.
- */
- if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) {
- change_notify_reply_packet(cnbp->request_buf,status);
- change_notify_remove(cnbp);
- }
+ while (fsp->notify->requests != NULL) {
+ change_notify_reply_packet(
+ fsp->notify->requests->request_buf, status);
+ change_notify_remove_request(fsp->notify->requests);
}
}
-/****************************************************************************
- Set the current change notify timeout to the lowest value across all service
- values.
-****************************************************************************/
-
-void set_change_notify_timeout(int val)
+void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
+ const char *path)
{
- if (val > 0) {
- cnotify->select_time = MIN(cnotify->select_time, val);
+ char *fullpath;
+
+ if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
+ DEBUG(0, ("asprintf failed\n"));
+ return;
}
-}
-/****************************************************************************
- Longest time to sleep for before doing a change notify scan.
-****************************************************************************/
+ notify_trigger(conn->notify_ctx, action, filter, fullpath);
+ SAFE_FREE(fullpath);
+}
-int change_notify_timeout(void)
+static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
{
- return cnotify->select_time;
-}
+ struct notify_change *change, *changes;
+ char *name2;
-/****************************************************************************
- Process the change notify queue. Note that this is only called as root.
- Returns True if there are still outstanding change notify requests on the
- queue.
-*****************************************************************************/
+ if (fsp->notify == NULL) {
+ /*
+ * Nobody is waiting, don't queue
+ */
+ return;
+ }
-BOOL process_pending_change_notify_queue(time_t t)
-{
- struct change_notify *cnbp, *next;
- uint16 vuid;
+ if (!(name2 = talloc_strdup(fsp->notify, name))) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ return;
+ }
- for (cnbp=change_notify_list; cnbp; cnbp=next) {
- next=cnbp->next;
+ string_replace(name2, '/', '\\');
- vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid);
+ /*
+ * Someone has triggered a notify previously, queue the change for
+ * later.
+ */
- if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) {
- DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name ));
- change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR);
- change_notify_remove(cnbp);
- }
+ if ((fsp->notify->num_changes > 1000) || (name == NULL)) {
+ /*
+ * The real number depends on the client buf, just provide a
+ * guard against a DoS here.
+ */
+ TALLOC_FREE(fsp->notify->changes);
+ TALLOC_FREE(name2);
+ fsp->notify->num_changes = -1;
+ return;
}
- return (change_notify_list != NULL);
-}
+ if (fsp->notify->num_changes == -1) {
+ return;
+ }
-/****************************************************************************
- Now queue an entry on the notify change list.
- We only need to save smb_size bytes from this incoming packet
- as we will always by returning a 'read the directory yourself'
- error.
-****************************************************************************/
+ if (!(changes = TALLOC_REALLOC_ARRAY(
+ fsp->notify, fsp->notify->changes,
+ struct notify_change, fsp->notify->num_changes+1))) {
+ DEBUG(0, ("talloc_realloc failed\n"));
+ TALLOC_FREE(name2);
+ return;
+ }
-BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags)
-{
- struct change_notify *cnbp;
+ fsp->notify->changes = changes;
- if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) {
- DEBUG(0,("change_notify_set: malloc fail !\n" ));
- return -1;
- }
+ change = &(fsp->notify->changes[fsp->notify->num_changes]);
- ZERO_STRUCTP(cnbp);
+ change->name = talloc_move(changes, &name2);
+ change->action = action;
+ fsp->notify->num_changes += 1;
- memcpy(cnbp->request_buf, inbuf, smb_size);
- cnbp->fsp = fsp;
- cnbp->conn = conn;
- cnbp->flags = flags;
- cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags);
-
- if (!cnbp->change_data) {
- SAFE_FREE(cnbp);
- return False;
+ if (fsp->notify->requests == NULL) {
+ /*
+ * Nobody is waiting, so don't send anything. The ot
+ */
+ return;
+ }
+
+ if (action == NOTIFY_ACTION_OLD_NAME) {
+ /*
+ * We have to send the two rename events in one reply. So hold
+ * the first part back.
+ */
+ return;
}
- DLIST_ADD(change_notify_list, cnbp);
+ /*
+ * Someone is waiting for the change, trigger the reply immediately.
+ *
+ * TODO: do we have to walk the lists of requests pending?
+ */
- /* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ change_notify_reply(fsp->notify->requests->request_buf,
+ fsp->notify->requests->max_param_count,
+ fsp->notify);
- return True;
+ change_notify_remove_request(fsp->notify->requests);
}
-int change_notify_fd(void)
+char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter)
{
- if (cnotify) {
- return cnotify->notification_fd;
- }
-
- return -1;
+ char *result = NULL;
+
+ result = talloc_strdup(mem_ctx, "");
+
+ if (filter & FILE_NOTIFY_CHANGE_FILE_NAME)
+ result = talloc_asprintf_append(result, "FILE_NAME|");
+ if (filter & FILE_NOTIFY_CHANGE_DIR_NAME)
+ result = talloc_asprintf_append(result, "DIR_NAME|");
+ if (filter & FILE_NOTIFY_CHANGE_ATTRIBUTES)
+ result = talloc_asprintf_append(result, "ATTRIBUTES|");
+ if (filter & FILE_NOTIFY_CHANGE_SIZE)
+ result = talloc_asprintf_append(result, "SIZE|");
+ if (filter & FILE_NOTIFY_CHANGE_LAST_WRITE)
+ result = talloc_asprintf_append(result, "LAST_WRITE|");
+ if (filter & FILE_NOTIFY_CHANGE_LAST_ACCESS)
+ result = talloc_asprintf_append(result, "LAST_ACCESS|");
+ if (filter & FILE_NOTIFY_CHANGE_CREATION)
+ result = talloc_asprintf_append(result, "CREATION|");
+ if (filter & FILE_NOTIFY_CHANGE_EA)
+ result = talloc_asprintf_append(result, "EA|");
+ if (filter & FILE_NOTIFY_CHANGE_SECURITY)
+ result = talloc_asprintf_append(result, "SECURITY|");
+ if (filter & FILE_NOTIFY_CHANGE_STREAM_NAME)
+ result = talloc_asprintf_append(result, "STREAM_NAME|");
+ if (filter & FILE_NOTIFY_CHANGE_STREAM_SIZE)
+ result = talloc_asprintf_append(result, "STREAM_SIZE|");
+ if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE)
+ result = talloc_asprintf_append(result, "STREAM_WRITE|");
+
+ if (result == NULL) return NULL;
+ if (*result == '\0') return result;
+
+ result[strlen(result)-1] = '\0';
+ return result;
}
-/****************************************************************************
- Initialise the change notify subsystem.
-****************************************************************************/
-
-BOOL init_change_notify(void)
+struct sys_notify_context *sys_notify_context_create(connection_struct *conn,
+ TALLOC_CTX *mem_ctx,
+ struct event_context *ev)
{
- cnotify = NULL;
-
-#if HAVE_KERNEL_CHANGE_NOTIFY
- if (cnotify == NULL && lp_kernel_change_notify())
- cnotify = kernel_notify_init();
-#endif
-#if HAVE_FAM_CHANGE_NOTIFY
- if (cnotify == NULL && lp_fam_change_notify())
- cnotify = fam_notify_init();
-#endif
- if (!cnotify) cnotify = hash_notify_init();
-
- if (!cnotify) {
- DEBUG(0,("Failed to init change notify system\n"));
- return False;
+ struct sys_notify_context *ctx;
+
+ if (!(ctx = TALLOC_P(mem_ctx, struct sys_notify_context))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
}
- return True;
+ ctx->ev = ev;
+ ctx->conn = conn;
+ ctx->private_data = NULL;
+ return ctx;
}
+
+NTSTATUS sys_notify_watch(struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data, void *handle)
+{
+ return SMB_VFS_NOTIFY_WATCH(ctx->conn, ctx, e, callback, private_data,
+ handle);
+}
+
diff --git a/source/smbd/notify_fam.c b/source/smbd/notify_fam.c
deleted file mode 100644
index b7f9a363321..00000000000
--- a/source/smbd/notify_fam.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * FAM file notification support.
- *
- * Copyright (c) James Peach 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "includes.h"
-
-#ifdef HAVE_FAM_CHANGE_NOTIFY
-
-#include <fam.h>
-
-#if !defined(HAVE_FAM_H_FAMCODES_TYPEDEF)
-/* Gamin provides this typedef which means we can't use 'enum FAMCodes' as per
- * every other FAM implementation. Phooey.
- */
-typedef enum FAMCodes FAMCodes;
-#endif
-
-/* NOTE: There are multiple versions of FAM floating around the net, each with
- * slight differences from the original SGI FAM implementation. In this file,
- * we rely only on the SGI features and do not assume any extensions. For
- * example, we do not look at FAMErrno, because it is not set by the original
- * implementation.
- *
- * Random FAM links:
- * http://oss.sgi.com/projects/fam/
- * http://savannah.nongnu.org/projects/fam/
- * http://sourceforge.net/projects/bsdfam/
- */
-
-struct fam_req_info
-{
- FAMRequest req;
- int generation;
- FAMCodes code;
- enum
- {
- /* We are waiting for an event. */
- FAM_REQ_MONITORING,
- /* An event has been receive, but we haven't been able to send it back
- * to the client yet. It is stashed in the code member.
- */
- FAM_REQ_FIRED
- } state;
-};
-
-/* Don't initialise this until the first register request. We want a single
- * FAM connection for each worker smbd. If we allow the master (parent) smbd to
- * open a FAM connection, multiple processes talking on the same socket will
- * undoubtedly create havoc.
- */
-static FAMConnection global_fc;
-static int global_fc_generation;
-
-#define FAM_TRACE 8
-#define FAM_TRACE_LOW 10
-
-#define FAM_EVENT_DRAIN ((uint32_t)(-1))
-
-static void * fam_register_notify(connection_struct * conn,
- char * path,
- uint32 flags);
-
-static BOOL fam_check_notify(connection_struct * conn,
- uint16_t vuid,
- char * path,
- uint32_t flags,
- void * data,
- time_t when);
-
-static void fam_remove_notify(void * data);
-
-static struct cnotify_fns global_fam_notify =
-{
- fam_register_notify,
- fam_check_notify,
- fam_remove_notify,
- -1,
- -1
-};
-
-/* Turn a FAM event code into a string. Don't rely on specific code values,
- * because that might not work across all flavours of FAM.
- */
-static const char *
-fam_event_str(FAMCodes code)
-{
- static const struct { FAMCodes code; const char * name; } evstr[] =
- {
- { FAMChanged, "FAMChanged"},
- { FAMDeleted, "FAMDeleted"},
- { FAMStartExecuting, "FAMStartExecuting"},
- { FAMStopExecuting, "FAMStopExecuting"},
- { FAMCreated, "FAMCreated"},
- { FAMMoved, "FAMMoved"},
- { FAMAcknowledge, "FAMAcknowledge"},
- { FAMExists, "FAMExists"},
- { FAMEndExist, "FAMEndExist"}
- };
-
- int i;
-
- for (i = 0; i < ARRAY_SIZE(evstr); ++i) {
- if (code == evstr[i].code)
- return(evstr[i].name);
- }
-
- return("<unknown>");
-}
-
-static BOOL
-fam_check_reconnect(void)
-{
- if (FAMCONNECTION_GETFD(&global_fc) < 0) {
- fstring name;
-
- global_fc_generation++;
- snprintf(name, sizeof(name), "smbd (%lu)", (unsigned long)sys_getpid());
-
- if (FAMOpen2(&global_fc, name) < 0) {
- DEBUG(0, ("failed to connect to FAM service\n"));
- return(False);
- }
- }
-
- global_fam_notify.notification_fd = FAMCONNECTION_GETFD(&global_fc);
- return(True);
-}
-
-static BOOL
-fam_monitor_path(connection_struct * conn,
- struct fam_req_info * info,
- const char * path,
- uint32 flags)
-{
- SMB_STRUCT_STAT st;
- pstring fullpath;
-
- DEBUG(FAM_TRACE, ("requesting FAM notifications for '%s'\n", path));
-
- /* FAM needs an absolute pathname. */
-
- /* It would be better to use reduce_name() here, but reduce_name does not
- * actually return the reduced result. How utterly un-useful.
- */
- pstrcpy(fullpath, path);
- if (!canonicalize_path(conn, fullpath)) {
- DEBUG(0, ("failed to canonicalize path '%s'\n", path));
- return(False);
- }
-
- if (*fullpath != '/') {
- DEBUG(0, ("canonicalized path '%s' into `%s`\n", path, fullpath));
- DEBUGADD(0, ("but expected an absolute path\n"));
- return(False);
- }
-
- if (SMB_VFS_STAT(conn, path, &st) < 0) {
- DEBUG(0, ("stat of '%s' failed: %s\n", path, strerror(errno)));
- return(False);
- }
- /* Start monitoring this file or directory. We hand the state structure to
- * both the caller and the FAM library so we can match up the caller's
- * status requests with FAM notifications.
- */
- if (S_ISDIR(st.st_mode)) {
- FAMMonitorDirectory(&global_fc, fullpath, &(info->req), info);
- } else {
- FAMMonitorFile(&global_fc, fullpath, &(info->req), info);
- }
-
- /* Grr. On IRIX, neither of the monitor functions return a status. */
-
- /* We will stay in initialising state until we see the FAMendExist message
- * for this file.
- */
- info->state = FAM_REQ_MONITORING;
- info->generation = global_fc_generation;
- return(True);
-}
-
-static BOOL
-fam_handle_event(const FAMCodes code, uint32 flags)
-{
-#define F_CHANGE_MASK (FILE_NOTIFY_CHANGE_FILE | \
- FILE_NOTIFY_CHANGE_ATTRIBUTES | \
- FILE_NOTIFY_CHANGE_SIZE | \
- FILE_NOTIFY_CHANGE_LAST_WRITE | \
- FILE_NOTIFY_CHANGE_LAST_ACCESS | \
- FILE_NOTIFY_CHANGE_CREATION | \
- FILE_NOTIFY_CHANGE_EA | \
- FILE_NOTIFY_CHANGE_SECURITY)
-
-#define F_DELETE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \
- FILE_NOTIFY_CHANGE_DIR_NAME)
-
-#define F_CREATE_MASK (FILE_NOTIFY_CHANGE_FILE_NAME | \
- FILE_NOTIFY_CHANGE_DIR_NAME)
-
- switch (code) {
- case FAMChanged:
- if (flags & F_CHANGE_MASK)
- return(True);
- break;
- case FAMDeleted:
- if (flags & F_DELETE_MASK)
- return(True);
- break;
- case FAMCreated:
- if (flags & F_CREATE_MASK)
- return(True);
- break;
- default:
- /* Ignore anything else. */
- break;
- }
-
- return(False);
-
-#undef F_CHANGE_MASK
-#undef F_DELETE_MASK
-#undef F_CREATE_MASK
-}
-
-static BOOL
-fam_pump_events(struct fam_req_info * info, uint32_t flags)
-{
- FAMEvent ev;
-
- for (;;) {
-
- /* If we are draining the event queue we must keep going until we find
- * the correct FAMAcknowledge event or the connection drops. Otherwise
- * we should stop when there are no more events pending.
- */
- if (flags != FAM_EVENT_DRAIN && !FAMPending(&global_fc)) {
- break;
- }
-
- if (FAMNextEvent(&global_fc, &ev) < 0) {
- DEBUG(0, ("failed to fetch pending FAM event\n"));
- DEBUGADD(0, ("resetting FAM connection\n"));
- FAMClose(&global_fc);
- FAMCONNECTION_GETFD(&global_fc) = -1;
- return(False);
- }
-
- DEBUG(FAM_TRACE_LOW, ("FAM event %s on '%s' for request %d\n",
- fam_event_str(ev.code), ev.filename, ev.fr.reqnum));
-
- switch (ev.code) {
- case FAMAcknowledge:
- /* FAM generates an ACK event when we cancel a monitor. We need
- * this to know when it is safe to free out request state
- * structure.
- */
- if (info->generation == global_fc_generation &&
- info->req.reqnum == ev.fr.reqnum &&
- flags == FAM_EVENT_DRAIN) {
- return(True);
- }
-
- case FAMEndExist:
- case FAMExists:
- /* Ignore these. FAM sends these enumeration events when we
- * start monitoring. If we are monitoring a directory, we will
- * get a FAMExists event for each directory entry.
- */
-
- /* TODO: we might be able to use these to implement recursive
- * monitoring of entire subtrees.
- */
- case FAMMoved:
- /* These events never happen. A move or rename shows up as a
- * create/delete pair.
- */
- case FAMStartExecuting:
- case FAMStopExecuting:
- /* We might get these, but we just don't care. */
- break;
-
- case FAMChanged:
- case FAMDeleted:
- case FAMCreated:
- if (info->generation != global_fc_generation) {
- /* Ignore this; the req number can't be matched. */
- break;
- }
-
- if (info->req.reqnum == ev.fr.reqnum) {
- /* This is the event the caller was interested in. */
- DEBUG(FAM_TRACE, ("handling FAM %s event on '%s'\n",
- fam_event_str(ev.code), ev.filename));
- /* Ignore events if we are draining this request. */
- if (flags != FAM_EVENT_DRAIN) {
- return(fam_handle_event(ev.code, flags));
- }
- break;
- } else {
- /* Caller doesn't want this event. Stash the result so we
- * can come back to it. Unfortunately, FAM doesn't
- * guarantee to give us back evinfo.
- */
- struct fam_req_info * evinfo =
- (struct fam_req_info *)ev.userdata;
-
- if (evinfo) {
- DEBUG(FAM_TRACE, ("storing FAM %s event for winter\n",
- fam_event_str(ev.code)));
- evinfo->state = FAM_REQ_FIRED;
- evinfo->code = ev.code;
- } else {
- DEBUG(2, ("received FAM %s notification for %s, "
- "but userdata was unexpectedly NULL\n",
- fam_event_str(ev.code), ev.filename));
- }
- break;
- }
-
- default:
- DEBUG(0, ("ignoring unknown FAM event code %d for `%s`\n",
- ev.code, ev.filename));
- }
- }
-
- /* No more notifications pending. */
- return(False);
-}
-
-static BOOL
-fam_test_connection(void)
-{
- FAMConnection fc;
-
- /* On IRIX FAMOpen2 leaks 960 bytes in 48 blocks. It's a deliberate leak
- * in the library and there's nothing we can do about it here.
- */
- if (FAMOpen2(&fc, "smbd probe") < 0)
- return(False);
-
- FAMClose(&fc);
- return(True);
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void *
-fam_register_notify(connection_struct * conn,
- char * path,
- uint32 flags)
-{
- struct fam_req_info * info;
-
- if (!fam_check_reconnect()) {
- return(False);
- }
-
- if ((info = SMB_MALLOC_P(struct fam_req_info)) == NULL) {
- DEBUG(0, ("malloc of %u bytes failed\n", (unsigned int)sizeof(struct fam_req_info)));
- return(NULL);
- }
-
- if (fam_monitor_path(conn, info, path, flags)) {
- return(info);
- } else {
- SAFE_FREE(info);
- return(NULL);
- }
-}
-
-static BOOL
-fam_check_notify(connection_struct * conn,
- uint16_t vuid,
- char * path,
- uint32_t flags,
- void * data,
- time_t when)
-{
- struct fam_req_info * info;
-
- info = (struct fam_req_info *)data;
- SMB_ASSERT(info != NULL);
-
- DEBUG(10, ("checking FAM events for `%s`\n", path));
-
- if (info->state == FAM_REQ_FIRED) {
- DEBUG(FAM_TRACE, ("handling previously fired FAM %s event\n",
- fam_event_str(info->code)));
- info->state = FAM_REQ_MONITORING;
- return(fam_handle_event(info->code, flags));
- }
-
- if (!fam_check_reconnect()) {
- return(False);
- }
-
- if (info->generation != global_fc_generation) {
- DEBUG(FAM_TRACE, ("reapplying stale FAM monitor to %s\n", path));
- fam_monitor_path(conn, info, path, flags);
- return(False);
- }
-
- return(fam_pump_events(info, flags));
-}
-
-static void
-fam_remove_notify(void * data)
-{
- struct fam_req_info * info;
-
- if ((info = (struct fam_req_info *)data) == NULL)
- return;
-
- /* No need to reconnect. If the FAM connection is gone, there's no need to
- * cancel and we can safely let FAMCancelMonitor fail. If it we
- * reconnected, then the generation check will stop us cancelling the wrong
- * request.
- */
-
- if (info->generation == global_fc_generation) {
- DEBUG(FAM_TRACE, ("removing FAM notification for request %d\n",
- info->req.reqnum));
- FAMCancelMonitor(&global_fc, &(info->req));
-
- /* Soak up all events until the FAMAcknowledge. We can't free
- * our request state until we are sure there are no more events in
- * flight.
- */
- fam_pump_events(info, FAM_EVENT_DRAIN);
- }
-
- SAFE_FREE(info);
-}
-
-struct cnotify_fns * fam_notify_init(void)
-{
- FAMCONNECTION_GETFD(&global_fc) = -1;
-
- if (!fam_test_connection()) {
- DEBUG(0, ("FAM file change notifications not available\n"));
- return(NULL);
- }
-
- DEBUG(FAM_TRACE, ("enabling FAM change notifications\n"));
- return &global_fam_notify;
-}
-
-#endif /* HAVE_FAM_CHANGE_NOTIFY */
diff --git a/source/smbd/notify_hash.c b/source/smbd/notify_hash.c
deleted file mode 100644
index 0787a3eec5e..00000000000
--- a/source/smbd/notify_hash.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- change notify handling - hash based implementation
- Copyright (C) Jeremy Allison 1994-1998
- Copyright (C) Andrew Tridgell 2000
-
- 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"
-
-struct change_data {
- time_t last_check_time; /* time we last checked this entry */
- struct timespec modify_time; /* Info from the directory we're monitoring. */
- struct timespec status_time; /* Info from the directory we're monitoring. */
- time_t total_time; /* Total time of all directory entries - don't care if it wraps. */
- unsigned int num_entries; /* Zero or the number of files in the directory. */
- unsigned int mode_sum;
- unsigned char name_hash[16];
-};
-
-
-/* Compare struct timespec. */
-#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec))
-
-/****************************************************************************
- Create the hash we will use to determine if the contents changed.
-*****************************************************************************/
-
-static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
- struct change_data *data, struct change_data *old_data)
-{
- SMB_STRUCT_STAT st;
- pstring full_name;
- char *p;
- const char *fname;
- size_t remaining_len;
- size_t fullname_len;
- struct smb_Dir *dp;
- long offset;
-
- ZERO_STRUCTP(data);
-
- if(SMB_VFS_STAT(conn,path, &st) == -1)
- return False;
-
- data->modify_time = get_mtimespec(&st);
- data->status_time = get_ctimespec(&st);
-
- if (old_data) {
- /*
- * Shortcut to avoid directory scan if the time
- * has changed - we always must return true then.
- */
- if (TIMESTAMP_NEQ(old_data->modify_time, data->modify_time) ||
- TIMESTAMP_NEQ(old_data->status_time, data->status_time) ) {
- return True;
- }
- }
-
- if (S_ISDIR(st.st_mode) &&
- (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0)
- {
- /* This is the case of a client wanting to know only when
- * the contents of a directory changes. Since any file
- * creation, rename or deletion will update the directory
- * timestamps, we don't need to create a hash.
- */
- return True;
- }
-
- if (lp_change_notify_timeout(SNUM(conn)) <= 0) {
- /* It change notify timeout has been disabled, never scan the directory. */
- return True;
- }
-
- /*
- * If we are to watch for changes that are only stored
- * in inodes of files, not in the directory inode, we must
- * scan the directory and produce a unique identifier with
- * which we can determine if anything changed. We use the
- * modify and change times from all the files in the
- * directory, added together (ignoring wrapping if it's
- * larger than the max time_t value).
- */
-
- dp = OpenDir(conn, path, NULL, 0);
- if (dp == NULL)
- return False;
-
- data->num_entries = 0;
-
- pstrcpy(full_name, path);
- pstrcat(full_name, "/");
-
- fullname_len = strlen(full_name);
- remaining_len = sizeof(full_name) - fullname_len - 1;
- p = &full_name[fullname_len];
-
- offset = 0;
- while ((fname = ReadDirName(dp, &offset))) {
- SET_STAT_INVALID(st);
- if(strequal(fname, ".") || strequal(fname, ".."))
- continue;
-
- if (!is_visible_file(conn, path, fname, &st, True))
- continue;
-
- data->num_entries++;
- safe_strcpy(p, fname, remaining_len);
-
- /*
- * Do the stat - but ignore errors.
- */
- if (!VALID_STAT(st)) {
- SMB_VFS_STAT(conn,full_name, &st);
- }
-
- /*
- * Always sum the times.
- */
-
- data->total_time += (st.st_mtime + st.st_ctime);
-
- /*
- * If requested hash the names.
- */
-
- if (flags & (FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_FILE)) {
- int i;
- unsigned char tmp_hash[16];
- mdfour(tmp_hash, (const unsigned char *)fname, strlen(fname));
- for (i=0;i<16;i++)
- data->name_hash[i] ^= tmp_hash[i];
- }
-
- /*
- * If requested sum the mode_t's.
- */
-
- if (flags & (FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SECURITY))
- data->mode_sum += st.st_mode;
- }
-
- CloseDir(dp);
-
- return True;
-}
-
-/****************************************************************************
- Register a change notify request.
-*****************************************************************************/
-
-static void *hash_register_notify(connection_struct *conn, char *path, uint32 flags)
-{
- struct change_data data;
-
- if (!notify_hash(conn, path, flags, &data, NULL))
- return NULL;
-
- data.last_check_time = time(NULL);
-
- return (void *)memdup(&data, sizeof(data));
-}
-
-/****************************************************************************
- Check if a change notify should be issued.
- A time of zero means instantaneous check - don't modify the last check time.
-*****************************************************************************/
-
-static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t)
-{
- struct change_data *data = (struct change_data *)datap;
- struct change_data data2;
- int cnto = lp_change_notify_timeout(SNUM(conn));
-
- if (t && cnto <= 0) {
- /* Change notify turned off on this share.
- * Only scan when (t==0) - we think something changed. */
- return False;
- }
-
- if (t && t < data->last_check_time + cnto) {
- return False;
- }
-
- if (!change_to_user(conn,vuid))
- return True;
- if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) {
- change_to_root_user();
- return True;
- }
-
- if (!notify_hash(conn, path, flags, &data2, data) ||
- TIMESTAMP_NEQ(data2.modify_time, data->modify_time) ||
- TIMESTAMP_NEQ(data2.status_time, data->status_time) ||
- data2.total_time != data->total_time ||
- data2.num_entries != data->num_entries ||
- data2.mode_sum != data->mode_sum ||
- memcmp(data2.name_hash, data->name_hash, sizeof(data2.name_hash))) {
- change_to_root_user();
- return True;
- }
-
- if (t) {
- data->last_check_time = t;
- }
-
- change_to_root_user();
-
- return False;
-}
-
-/****************************************************************************
- Remove a change notify data structure.
-*****************************************************************************/
-
-static void hash_remove_notify(void *datap)
-{
- free(datap);
-}
-
-/****************************************************************************
- Setup hash based change notify.
-****************************************************************************/
-
-struct cnotify_fns *hash_notify_init(void)
-{
- static struct cnotify_fns cnotify;
-
- cnotify.register_notify = hash_register_notify;
- cnotify.check_notify = hash_check_notify;
- cnotify.remove_notify = hash_remove_notify;
- cnotify.select_time = 60; /* Start with 1 minute default. */
- cnotify.notification_fd = -1;
-
- return &cnotify;
-}
-
-/*
- change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess);
- change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR);
-
- chain_size = 0;
- file_chain_reset();
-
- uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID :
- SVAL(cnbp->request_buf,smb_uid);
-*/
diff --git a/source/smbd/notify_inotify.c b/source/smbd/notify_inotify.c
new file mode 100644
index 00000000000..5fb414de4cc
--- /dev/null
+++ b/source/smbd/notify_inotify.c
@@ -0,0 +1,425 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2006
+
+ 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.
+*/
+
+/*
+ notify implementation using inotify
+*/
+
+#include "includes.h"
+
+#ifdef HAVE_INOTIFY
+
+#include <linux/inotify.h>
+#include <asm/unistd.h>
+
+#ifndef HAVE_INOTIFY_INIT
+/*
+ glibc doesn't define these functions yet (as of March 2006)
+*/
+static int inotify_init(void)
+{
+ return syscall(__NR_inotify_init);
+}
+
+static int inotify_add_watch(int fd, const char *path, __u32 mask)
+{
+ return syscall(__NR_inotify_add_watch, fd, path, mask);
+}
+
+static int inotify_rm_watch(int fd, int wd)
+{
+ return syscall(__NR_inotify_rm_watch, fd, wd);
+}
+#endif
+
+
+/* older glibc headers don't have these defines either */
+#ifndef IN_ONLYDIR
+#define IN_ONLYDIR 0x01000000
+#endif
+#ifndef IN_MASK_ADD
+#define IN_MASK_ADD 0x20000000
+#endif
+
+struct inotify_private {
+ struct sys_notify_context *ctx;
+ int fd;
+ struct inotify_watch_context *watches;
+};
+
+struct inotify_watch_context {
+ struct inotify_watch_context *next, *prev;
+ struct inotify_private *in;
+ int wd;
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev);
+ void *private_data;
+ uint32_t mask; /* the inotify mask */
+ uint32_t filter; /* the windows completion filter */
+ const char *path;
+};
+
+
+/*
+ destroy the inotify private context
+*/
+static int inotify_destructor(struct inotify_private *in)
+{
+ close(in->fd);
+ return 0;
+}
+
+
+/*
+ see if a particular event from inotify really does match a requested
+ notify event in SMB
+*/
+static BOOL filter_match(struct inotify_watch_context *w,
+ struct inotify_event *e)
+{
+ DEBUG(10, ("filter_match: e->mask=%x, w->mask=%x, w->filter=%x\n",
+ e->mask, w->mask, w->filter));
+
+ if ((e->mask & w->mask) == 0) {
+ /* this happens because inotify_add_watch() coalesces watches on the same
+ path, oring their masks together */
+ return False;
+ }
+
+ /* SMB separates the filters for files and directories */
+ if (e->mask & IN_ISDIR) {
+ if ((w->filter & FILE_NOTIFY_CHANGE_DIR_NAME) == 0) {
+ return False;
+ }
+ } else {
+ if ((e->mask & IN_ATTRIB) &&
+ (w->filter & (FILE_NOTIFY_CHANGE_ATTRIBUTES|
+ FILE_NOTIFY_CHANGE_LAST_WRITE|
+ FILE_NOTIFY_CHANGE_LAST_ACCESS|
+ FILE_NOTIFY_CHANGE_EA|
+ FILE_NOTIFY_CHANGE_SECURITY))) {
+ return True;
+ }
+ if ((e->mask & IN_MODIFY) &&
+ (w->filter & FILE_NOTIFY_CHANGE_ATTRIBUTES)) {
+ return True;
+ }
+ if ((w->filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) {
+ return False;
+ }
+ }
+
+ return True;
+}
+
+
+
+/*
+ dispatch one inotify event
+
+ the cookies are used to correctly handle renames
+*/
+static void inotify_dispatch(struct inotify_private *in,
+ struct inotify_event *e,
+ uint32_t prev_cookie,
+ struct inotify_event *e2)
+{
+ struct inotify_watch_context *w, *next;
+ struct notify_event ne;
+
+ DEBUG(10, ("inotify_dispatch called with mask=%x, name=[%s]\n",
+ e->mask, e->len ? e->name : ""));
+
+ /* ignore extraneous events, such as unmount and IN_IGNORED events */
+ if ((e->mask & (IN_ATTRIB|IN_MODIFY|IN_CREATE|IN_DELETE|
+ IN_MOVED_FROM|IN_MOVED_TO)) == 0) {
+ return;
+ }
+
+ /* map the inotify mask to a action. This gets complicated for
+ renames */
+ if (e->mask & IN_CREATE) {
+ ne.action = NOTIFY_ACTION_ADDED;
+ } else if (e->mask & IN_DELETE) {
+ ne.action = NOTIFY_ACTION_REMOVED;
+ } else if (e->mask & IN_MOVED_FROM) {
+ if (e2 != NULL && e2->cookie == e->cookie) {
+ ne.action = NOTIFY_ACTION_OLD_NAME;
+ } else {
+ ne.action = NOTIFY_ACTION_REMOVED;
+ }
+ } else if (e->mask & IN_MOVED_TO) {
+ if (e->cookie == prev_cookie) {
+ ne.action = NOTIFY_ACTION_NEW_NAME;
+ } else {
+ ne.action = NOTIFY_ACTION_ADDED;
+ }
+ } else {
+ ne.action = NOTIFY_ACTION_MODIFIED;
+ }
+ ne.path = e->name;
+
+ DEBUG(10, ("inotify_dispatch: ne.action = %d, ne.path = %s\n",
+ ne.action, ne.path));
+
+ /* find any watches that have this watch descriptor */
+ for (w=in->watches;w;w=next) {
+ next = w->next;
+ if (w->wd == e->wd && filter_match(w, e)) {
+ w->callback(in->ctx, w->private_data, &ne);
+ }
+ }
+
+ /* SMB expects a file rename to generate three events, two for
+ the rename and the other for a modify of the
+ destination. Strange! */
+ if (ne.action != NOTIFY_ACTION_NEW_NAME ||
+ (e->mask & IN_ISDIR) != 0) {
+ return;
+ }
+
+ ne.action = NOTIFY_ACTION_MODIFIED;
+ e->mask = IN_ATTRIB;
+
+ for (w=in->watches;w;w=next) {
+ next = w->next;
+ if (w->wd == e->wd && filter_match(w, e) &&
+ !(w->filter & FILE_NOTIFY_CHANGE_CREATION)) {
+ w->callback(in->ctx, w->private_data, &ne);
+ }
+ }
+}
+
+/*
+ called when the kernel has some events for us
+*/
+static void inotify_handler(struct event_context *ev, struct fd_event *fde,
+ uint16_t flags, void *private_data)
+{
+ struct inotify_private *in = talloc_get_type(private_data,
+ struct inotify_private);
+ int bufsize = 0;
+ struct inotify_event *e0, *e;
+ uint32_t prev_cookie=0;
+
+ /*
+ we must use FIONREAD as we cannot predict the length of the
+ filenames, and thus can't know how much to allocate
+ otherwise
+ */
+ if (ioctl(in->fd, FIONREAD, &bufsize) != 0 ||
+ bufsize == 0) {
+ DEBUG(0,("No data on inotify fd?!\n"));
+ return;
+ }
+
+ e0 = e = (struct inotify_event *)talloc_size(in, bufsize);
+ if (e == NULL) return;
+
+ if (read(in->fd, e0, bufsize) != bufsize) {
+ DEBUG(0,("Failed to read all inotify data\n"));
+ talloc_free(e0);
+ return;
+ }
+
+ /* we can get more than one event in the buffer */
+ while (bufsize >= sizeof(*e)) {
+ struct inotify_event *e2 = NULL;
+ bufsize -= e->len + sizeof(*e);
+ if (bufsize >= sizeof(*e)) {
+ e2 = (struct inotify_event *)(e->len + sizeof(*e) + (char *)e);
+ }
+ inotify_dispatch(in, e, prev_cookie, e2);
+ prev_cookie = e->cookie;
+ e = e2;
+ }
+
+ talloc_free(e0);
+}
+
+/*
+ setup the inotify handle - called the first time a watch is added on
+ this context
+*/
+static NTSTATUS inotify_setup(struct sys_notify_context *ctx)
+{
+ struct inotify_private *in;
+
+ if (!lp_parm_bool(-1, "notify", "inotify", True)) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+
+ in = talloc(ctx, struct inotify_private);
+ NT_STATUS_HAVE_NO_MEMORY(in);
+ in->fd = inotify_init();
+ if (in->fd == -1) {
+ DEBUG(0,("Failed to init inotify - %s\n", strerror(errno)));
+ talloc_free(in);
+ return map_nt_error_from_unix(errno);
+ }
+ in->ctx = ctx;
+ in->watches = NULL;
+
+ ctx->private_data = in;
+ talloc_set_destructor(in, inotify_destructor);
+
+ /* add a event waiting for the inotify fd to be readable */
+ event_add_fd(ctx->ev, in, in->fd, EVENT_FD_READ, inotify_handler, in);
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ map from a change notify mask to a inotify mask. Remove any bits
+ which we can handle
+*/
+static const struct {
+ uint32_t notify_mask;
+ uint32_t inotify_mask;
+} inotify_mapping[] = {
+ {FILE_NOTIFY_CHANGE_FILE_NAME, IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO},
+ {FILE_NOTIFY_CHANGE_DIR_NAME, IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO},
+ {FILE_NOTIFY_CHANGE_ATTRIBUTES, IN_ATTRIB|IN_MOVED_TO|IN_MOVED_FROM|IN_MODIFY},
+ {FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB},
+ {FILE_NOTIFY_CHANGE_LAST_ACCESS, IN_ATTRIB},
+ {FILE_NOTIFY_CHANGE_EA, IN_ATTRIB},
+ {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB}
+};
+
+static uint32_t inotify_map(struct notify_entry *e)
+{
+ int i;
+ uint32_t out=0;
+ for (i=0;i<ARRAY_SIZE(inotify_mapping);i++) {
+ if (inotify_mapping[i].notify_mask & e->filter) {
+ out |= inotify_mapping[i].inotify_mask;
+ e->filter &= ~inotify_mapping[i].notify_mask;
+ }
+ }
+ return out;
+}
+
+/*
+ destroy a watch
+*/
+static int watch_destructor(struct inotify_watch_context *w)
+{
+ struct inotify_private *in = w->in;
+ int wd = w->wd;
+ DLIST_REMOVE(w->in->watches, w);
+
+ /* only rm the watch if its the last one with this wd */
+ for (w=in->watches;w;w=w->next) {
+ if (w->wd == wd) break;
+ }
+ if (w == NULL) {
+ DEBUG(10, ("Deleting inotify watch %d\n", wd));
+ if (inotify_rm_watch(in->fd, wd) == -1) {
+ DEBUG(1, ("inotify_rm_watch returned %s\n",
+ strerror(errno)));
+ }
+
+ }
+ return 0;
+}
+
+
+/*
+ add a watch. The watch is removed when the caller calls
+ talloc_free() on *handle
+*/
+NTSTATUS inotify_watch(struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data,
+ void *handle_p)
+{
+ struct inotify_private *in;
+ int wd;
+ uint32_t mask;
+ struct inotify_watch_context *w;
+ uint32_t filter = e->filter;
+ void **handle = (void **)handle_p;
+
+ /* maybe setup the inotify fd */
+ if (ctx->private_data == NULL) {
+ NTSTATUS status;
+ status = inotify_setup(ctx);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+
+ in = talloc_get_type(ctx->private_data, struct inotify_private);
+
+ mask = inotify_map(e);
+ if (mask == 0) {
+ /* this filter can't be handled by inotify */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* using IN_MASK_ADD allows us to cope with inotify() returning the same
+ watch descriptor for muliple watches on the same path */
+ mask |= (IN_MASK_ADD | IN_ONLYDIR);
+
+ /* get a new watch descriptor for this path */
+ wd = inotify_add_watch(in->fd, e->path, mask);
+ if (wd == -1) {
+ e->filter = filter;
+ DEBUG(1, ("inotify_add_watch returned %s\n", strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
+
+ DEBUG(10, ("inotify_add_watch for %s mask %x returned wd %d\n",
+ e->path, mask, wd));
+
+ w = talloc(in, struct inotify_watch_context);
+ if (w == NULL) {
+ inotify_rm_watch(in->fd, wd);
+ e->filter = filter;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ w->in = in;
+ w->wd = wd;
+ w->callback = callback;
+ w->private_data = private_data;
+ w->mask = mask;
+ w->filter = filter;
+ w->path = talloc_strdup(w, e->path);
+ if (w->path == NULL) {
+ inotify_rm_watch(in->fd, wd);
+ e->filter = filter;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*handle) = w;
+
+ DLIST_ADD(in->watches, w);
+
+ /* the caller frees the handle to stop watching */
+ talloc_set_destructor(w, watch_destructor);
+
+ return NT_STATUS_OK;
+}
+
+#endif
diff --git a/source/smbd/notify_internal.c b/source/smbd/notify_internal.c
new file mode 100644
index 00000000000..72b96049350
--- /dev/null
+++ b/source/smbd/notify_internal.c
@@ -0,0 +1,686 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ this is the change notify database. It implements mechanisms for
+ storing current change notify waiters in a tdb, and checking if a
+ given event matches any of the stored notify waiiters.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_notify.h"
+
+struct notify_context {
+ struct tdb_wrap *w;
+ struct server_id server;
+ struct messaging_context *messaging_ctx;
+ struct notify_list *list;
+ struct notify_array *array;
+ int seqnum;
+ struct sys_notify_context *sys_notify_ctx;
+};
+
+
+struct notify_list {
+ struct notify_list *next, *prev;
+ void *private_data;
+ void (*callback)(void *, const struct notify_event *);
+ void *sys_notify_handle;
+ int depth;
+};
+
+#define NOTIFY_KEY "notify array"
+
+#define NOTIFY_ENABLE "notify:enable"
+#define NOTIFY_ENABLE_DEFAULT True
+
+static NTSTATUS notify_remove_all(struct notify_context *notify,
+ const struct server_id *server);
+static void notify_handler(struct messaging_context *msg_ctx, void *private_data,
+ uint32_t msg_type, struct server_id server_id, DATA_BLOB *data);
+
+/*
+ destroy the notify context
+*/
+static int notify_destructor(struct notify_context *notify)
+{
+ messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify);
+
+ if (notify->list != NULL) {
+ notify_remove_all(notify, &notify->server);
+ }
+
+ return 0;
+}
+
+/*
+ Open up the notify.tdb database. You should close it down using
+ talloc_free(). We need the messaging_ctx to allow for notifications
+ via internal messages
+*/
+struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
+ struct messaging_context *messaging_ctx,
+ struct event_context *ev,
+ connection_struct *conn)
+{
+ struct notify_context *notify;
+
+ if (!lp_change_notify(conn->params)) {
+ return NULL;
+ }
+
+ notify = talloc(mem_ctx, struct notify_context);
+ if (notify == NULL) {
+ return NULL;
+ }
+
+ notify->w = tdb_wrap_open(notify, lock_path("notify.tdb"),
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ O_RDWR|O_CREAT, 0644);
+ if (notify->w == NULL) {
+ talloc_free(notify);
+ return NULL;
+ }
+
+ notify->server = server;
+ notify->messaging_ctx = messaging_ctx;
+ notify->list = NULL;
+ notify->array = NULL;
+ notify->seqnum = tdb_get_seqnum(notify->w->tdb);
+
+ talloc_set_destructor(notify, notify_destructor);
+
+ /* register with the messaging subsystem for the notify
+ message type */
+ messaging_register(notify->messaging_ctx, notify,
+ MSG_PVFS_NOTIFY, notify_handler);
+
+ notify->sys_notify_ctx = sys_notify_context_create(conn, notify, ev);
+
+ return notify;
+}
+
+
+/*
+ lock the notify db
+*/
+static NTSTATUS notify_lock(struct notify_context *notify)
+{
+ if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ unlock the notify db
+*/
+static void notify_unlock(struct notify_context *notify)
+{
+ tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY);
+}
+
+/*
+ load the notify array
+*/
+static NTSTATUS notify_load(struct notify_context *notify)
+{
+ TDB_DATA dbuf;
+ DATA_BLOB blob;
+ NTSTATUS status;
+ int seqnum;
+
+ seqnum = tdb_get_seqnum(notify->w->tdb);
+
+ if (seqnum == notify->seqnum && notify->array != NULL) {
+ return NT_STATUS_OK;
+ }
+
+ notify->seqnum = seqnum;
+
+ talloc_free(notify->array);
+ notify->array = talloc_zero(notify, struct notify_array);
+ NT_STATUS_HAVE_NO_MEMORY(notify->array);
+
+ dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY);
+ if (dbuf.dptr == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ blob.data = (uint8 *)dbuf.dptr;
+ blob.length = dbuf.dsize;
+
+ status = ndr_pull_struct_blob(&blob, notify->array, notify->array,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_array);
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_load:\n"));
+ NDR_PRINT_DEBUG(notify_array, notify->array);
+ }
+
+ free(dbuf.dptr);
+
+ return status;
+}
+
+/*
+ compare notify entries for sorting
+*/
+static int notify_compare(const void *p1, const void *p2)
+{
+ const struct notify_entry *e1 = (const struct notify_entry *)p1;
+ const struct notify_entry *e2 = (const struct notify_entry *)p2;
+ return strcmp(e1->path, e2->path);
+}
+
+/*
+ save the notify array
+*/
+static NTSTATUS notify_save(struct notify_context *notify)
+{
+ TDB_DATA dbuf;
+ DATA_BLOB blob;
+ NTSTATUS status;
+ int ret;
+ TALLOC_CTX *tmp_ctx;
+
+ /* if possible, remove some depth arrays */
+ while (notify->array->num_depths > 0 &&
+ notify->array->depth[notify->array->num_depths-1].num_entries == 0) {
+ notify->array->num_depths--;
+ }
+
+ /* we might just be able to delete the record */
+ if (notify->array->num_depths == 0) {
+ ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY);
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ return NT_STATUS_OK;
+ }
+
+ tmp_ctx = talloc_new(notify);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ status = ndr_push_struct_blob(&blob, tmp_ctx, notify->array,
+ (ndr_push_flags_fn_t)ndr_push_notify_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_save:\n"));
+ NDR_PRINT_DEBUG(notify_array, notify->array);
+ }
+
+ dbuf.dptr = (char *)blob.data;
+ dbuf.dsize = blob.length;
+
+ ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE);
+ talloc_free(tmp_ctx);
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ handle incoming notify messages
+*/
+static void notify_handler(struct messaging_context *msg_ctx, void *private_data,
+ uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
+{
+ struct notify_context *notify = talloc_get_type(private_data, struct notify_context);
+ NTSTATUS status;
+ struct notify_event ev;
+ TALLOC_CTX *tmp_ctx = talloc_new(notify);
+ struct notify_list *listel;
+
+ if (tmp_ctx == NULL) {
+ return;
+ }
+
+ status = ndr_pull_struct_blob(data, tmp_ctx, &ev,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_event);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ for (listel=notify->list;listel;listel=listel->next) {
+ if (listel->private_data == ev.private_data) {
+ listel->callback(listel->private_data, &ev);
+ break;
+ }
+ }
+
+ talloc_free(tmp_ctx);
+}
+
+/*
+ callback from sys_notify telling us about changes from the OS
+*/
+static void sys_notify_callback(struct sys_notify_context *ctx,
+ void *ptr, struct notify_event *ev)
+{
+ struct notify_list *listel = talloc_get_type(ptr, struct notify_list);
+ ev->private_data = listel;
+ DEBUG(10, ("sys_notify_callback called with action=%d, for %s\n",
+ ev->action, ev->path));
+ listel->callback(listel->private_data, ev);
+}
+
+/*
+ add an entry to the notify array
+*/
+static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_entry *e,
+ void *private_data, int depth)
+{
+ int i;
+ struct notify_depth *d;
+ struct notify_entry *ee;
+
+ /* possibly expand the depths array */
+ if (depth >= notify->array->num_depths) {
+ d = talloc_realloc(notify->array, notify->array->depth,
+ struct notify_depth, depth+1);
+ NT_STATUS_HAVE_NO_MEMORY(d);
+ for (i=notify->array->num_depths;i<=depth;i++) {
+ ZERO_STRUCT(d[i]);
+ }
+ notify->array->depth = d;
+ notify->array->num_depths = depth+1;
+ }
+ d = &notify->array->depth[depth];
+
+ /* expand the entries array */
+ ee = talloc_realloc(notify->array->depth, d->entries, struct notify_entry,
+ d->num_entries+1);
+ NT_STATUS_HAVE_NO_MEMORY(ee);
+ d->entries = ee;
+
+ d->entries[d->num_entries] = *e;
+ d->entries[d->num_entries].private_data = private_data;
+ d->entries[d->num_entries].server = notify->server;
+ d->entries[d->num_entries].path_len = strlen(e->path);
+ d->num_entries++;
+
+ d->max_mask |= e->filter;
+ d->max_mask_subdir |= e->subdir_filter;
+
+ if (d->num_entries > 1) {
+ qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare);
+ }
+
+ /* recalculate the maximum masks */
+ d->max_mask = 0;
+ d->max_mask_subdir = 0;
+
+ for (i=0;i<d->num_entries;i++) {
+ d->max_mask |= d->entries[i].filter;
+ d->max_mask_subdir |= d->entries[i].subdir_filter;
+ }
+
+ return notify_save(notify);
+}
+
+/*
+ add a notify watch. This is called when a notify is first setup on a open
+ directory handle.
+*/
+NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
+ void (*callback)(void *, const struct notify_event *),
+ void *private_data)
+{
+ struct notify_entry e = *e0;
+ NTSTATUS status;
+ char *tmp_path = NULL;
+ struct notify_list *listel;
+ size_t len;
+ int depth;
+
+ /* see if change notify is enabled at all */
+ if (notify == NULL) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ status = notify_lock(notify);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ /* cope with /. on the end of the path */
+ len = strlen(e.path);
+ if (len > 1 && e.path[len-1] == '.' && e.path[len-2] == '/') {
+ tmp_path = talloc_strndup(notify, e.path, len-2);
+ if (tmp_path == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ e.path = tmp_path;
+ }
+
+ depth = count_chars(e.path, '/');
+
+ listel = talloc_zero(notify, struct notify_list);
+ if (listel == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ listel->private_data = private_data;
+ listel->callback = callback;
+ listel->depth = depth;
+ DLIST_ADD(notify->list, listel);
+
+ /* ignore failures from sys_notify */
+ if (notify->sys_notify_ctx != NULL) {
+ /*
+ this call will modify e.filter and e.subdir_filter
+ to remove bits handled by the backend
+ */
+ status = sys_notify_watch(notify->sys_notify_ctx, &e,
+ sys_notify_callback, listel,
+ &listel->sys_notify_handle);
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(listel, listel->sys_notify_handle);
+ }
+ }
+
+ /* if the system notify handler couldn't handle some of the
+ filter bits, or couldn't handle a request for recursion
+ then we need to install it in the array used for the
+ intra-samba notify handling */
+ if (e.filter != 0 || e.subdir_filter != 0) {
+ status = notify_add_array(notify, &e, private_data, depth);
+ }
+
+done:
+ notify_unlock(notify);
+ talloc_free(tmp_path);
+
+ return status;
+}
+
+/*
+ remove a notify watch. Called when the directory handle is closed
+*/
+NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
+{
+ NTSTATUS status;
+ struct notify_list *listel;
+ int i, depth;
+ struct notify_depth *d;
+
+ /* see if change notify is enabled at all */
+ if (notify == NULL) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ for (listel=notify->list;listel;listel=listel->next) {
+ if (listel->private_data == private_data) {
+ DLIST_REMOVE(notify->list, listel);
+ break;
+ }
+ }
+ if (listel == NULL) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ depth = listel->depth;
+
+ talloc_free(listel);
+
+ status = notify_lock(notify);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ notify_unlock(notify);
+ return status;
+ }
+
+ if (depth >= notify->array->num_depths) {
+ notify_unlock(notify);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ /* we only have to search at the depth of this element */
+ d = &notify->array->depth[depth];
+
+ for (i=0;i<d->num_entries;i++) {
+ if (private_data == d->entries[i].private_data &&
+ cluster_id_equal(&notify->server, &d->entries[i].server)) {
+ break;
+ }
+ }
+ if (i == d->num_entries) {
+ notify_unlock(notify);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (i < d->num_entries-1) {
+ memmove(&d->entries[i], &d->entries[i+1],
+ sizeof(d->entries[i])*(d->num_entries-(i+1)));
+ }
+ d->num_entries--;
+
+ status = notify_save(notify);
+
+ notify_unlock(notify);
+
+ return status;
+}
+
+/*
+ remove all notify watches for a messaging server
+*/
+static NTSTATUS notify_remove_all(struct notify_context *notify,
+ const struct server_id *server)
+{
+ NTSTATUS status;
+ int i, depth, del_count=0;
+
+ status = notify_lock(notify);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ notify_unlock(notify);
+ return status;
+ }
+
+ /* we have to search for all entries across all depths, looking for matches
+ for the server id */
+ for (depth=0;depth<notify->array->num_depths;depth++) {
+ struct notify_depth *d = &notify->array->depth[depth];
+ for (i=0;i<d->num_entries;i++) {
+ if (cluster_id_equal(server, &d->entries[i].server)) {
+ if (i < d->num_entries-1) {
+ memmove(&d->entries[i], &d->entries[i+1],
+ sizeof(d->entries[i])*(d->num_entries-(i+1)));
+ }
+ i--;
+ d->num_entries--;
+ del_count++;
+ }
+ }
+ }
+
+ if (del_count > 0) {
+ status = notify_save(notify);
+ }
+
+ notify_unlock(notify);
+
+ return status;
+}
+
+
+/*
+ send a notify message to another messaging server
+*/
+static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *e,
+ const char *path, uint32_t action)
+{
+ struct notify_event ev;
+ DATA_BLOB data;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx;
+
+ ev.action = action;
+ ev.path = path;
+ ev.private_data = e->private_data;
+
+ tmp_ctx = talloc_new(notify);
+
+ status = ndr_push_struct_blob(&data, tmp_ctx, &ev,
+ (ndr_push_flags_fn_t)ndr_push_notify_event);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ status = messaging_send(notify->messaging_ctx, e->server,
+ MSG_PVFS_NOTIFY, &data);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+
+/*
+ trigger a notify message for anyone waiting on a matching event
+
+ This function is called a lot, and needs to be very fast. The unusual data structure
+ and traversal is designed to be fast in the average case, even for large numbers of
+ notifies
+*/
+void notify_trigger(struct notify_context *notify,
+ uint32_t action, uint32_t filter, const char *path)
+{
+ NTSTATUS status;
+ int depth;
+ const char *p, *next_p;
+
+ DEBUG(10, ("notify_trigger called action=0x%x, filter=0x%x, "
+ "path=%s\n", (unsigned)action, (unsigned)filter, path));
+
+ /* see if change notify is enabled at all */
+ if (notify == NULL) {
+ return;
+ }
+
+ again:
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
+
+ /* loop along the given path, working with each directory depth separately */
+ for (depth=0,p=path;
+ p && depth < notify->array->num_depths;
+ p=next_p,depth++) {
+ int p_len = p - path;
+ int min_i, max_i, i;
+ struct notify_depth *d = &notify->array->depth[depth];
+ next_p = strchr(p+1, '/');
+
+ /* see if there are any entries at this depth */
+ if (d->num_entries == 0) continue;
+
+ /* try to skip based on the maximum mask. If next_p is
+ NULL then we know it will be a 'this directory'
+ match, otherwise it must be a subdir match */
+ if (next_p != NULL) {
+ if (0 == (filter & d->max_mask_subdir)) {
+ continue;
+ }
+ } else {
+ if (0 == (filter & d->max_mask)) {
+ continue;
+ }
+ }
+
+ /* we know there is an entry here worth looking
+ for. Use a bisection search to find the first entry
+ with a matching path */
+ min_i = 0;
+ max_i = d->num_entries-1;
+
+ while (min_i < max_i) {
+ struct notify_entry *e;
+ int cmp;
+ i = (min_i+max_i)/2;
+ e = &d->entries[i];
+ cmp = strncmp(path, e->path, p_len);
+ if (cmp == 0) {
+ if (p_len == e->path_len) {
+ max_i = i;
+ } else {
+ max_i = i-1;
+ }
+ } else if (cmp < 0) {
+ max_i = i-1;
+ } else {
+ min_i = i+1;
+ }
+ }
+
+ if (min_i != max_i) {
+ /* none match */
+ continue;
+ }
+
+ /* we now know that the entries start at min_i */
+ for (i=min_i;i<d->num_entries;i++) {
+ struct notify_entry *e = &d->entries[i];
+ if (p_len != e->path_len ||
+ strncmp(path, e->path, p_len) != 0) break;
+ if (next_p != NULL) {
+ if (0 == (filter & e->subdir_filter)) {
+ continue;
+ }
+ } else {
+ if (0 == (filter & e->filter)) {
+ continue;
+ }
+ }
+ status = notify_send(notify, e, path + e->path_len + 1,
+ action);
+
+ if (NT_STATUS_EQUAL(
+ status, NT_STATUS_INVALID_HANDLE)) {
+ struct server_id server = e->server;
+
+ DEBUG(10, ("Deleting notify entries for "
+ "process %s because it's gone\n",
+ procid_str_static(&e->server.id)));
+ notify_remove_all(notify, &server);
+ goto again;
+ }
+ }
+ }
+}
diff --git a/source/smbd/notify_kernel.c b/source/smbd/notify_kernel.c
deleted file mode 100644
index 0c20effc3d1..00000000000
--- a/source/smbd/notify_kernel.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 3.0
- change notify handling - linux kernel based implementation
- Copyright (C) Andrew Tridgell 2000
-
- 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"
-
-#if HAVE_KERNEL_CHANGE_NOTIFY
-
-#define FD_PENDING_SIZE 20
-static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE];
-static SIG_ATOMIC_T signals_received;
-
-#ifndef DN_ACCESS
-#define DN_ACCESS 0x00000001 /* File accessed in directory */
-#define DN_MODIFY 0x00000002 /* File modified in directory */
-#define DN_CREATE 0x00000004 /* File created in directory */
-#define DN_DELETE 0x00000008 /* File removed from directory */
-#define DN_RENAME 0x00000010 /* File renamed in directory */
-#define DN_ATTRIB 0x00000020 /* File changed attribute */
-#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
-#endif
-
-
-#ifndef RT_SIGNAL_NOTIFY
-#define RT_SIGNAL_NOTIFY (SIGRTMIN+2)
-#endif
-
-#ifndef F_SETSIG
-#define F_SETSIG 10
-#endif
-
-#ifndef F_NOTIFY
-#define F_NOTIFY 1026
-#endif
-
-/****************************************************************************
- This is the structure to keep the information needed to
- determine if a directory has changed.
-*****************************************************************************/
-
-struct change_data {
- int directory_handle;
-};
-
-/****************************************************************************
- The signal handler for change notify.
- The Linux kernel has a bug in that we should be able to block any
- further delivery of RT signals until the kernel_check_notify() function
- unblocks them, but it seems that any signal mask we're setting here is
- being overwritten on exit from this handler. I should create a standalone
- test case for the kernel hackers. JRA.
-*****************************************************************************/
-
-static void signal_handler(int sig, siginfo_t *info, void *unused)
-{
- if (signals_received < FD_PENDING_SIZE - 1) {
- fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd;
- signals_received++;
- } /* Else signal is lost. */
- sys_select_signal(RT_SIGNAL_NOTIFY);
-}
-
-/****************************************************************************
- Check if a change notify should be issued.
- time non-zero means timeout check (used for hash). Ignore this (async method
- where time is zero will be used instead).
-*****************************************************************************/
-
-static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t)
-{
- struct change_data *data = (struct change_data *)datap;
- int i;
- BOOL ret = False;
-
- if (t)
- return False;
-
- BlockSignals(True, RT_SIGNAL_NOTIFY);
- for (i = 0; i < signals_received; i++) {
- if (data->directory_handle == (int)fd_pending_array[i]) {
- DEBUG(3,("kernel_check_notify: kernel change notify on %s fd[%d]=%d (signals_received=%d)\n",
- path, i, (int)fd_pending_array[i], (int)signals_received ));
-
- 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));
- }
- data->directory_handle = -1;
- signals_received--;
- ret = True;
- break;
- }
- }
- BlockSignals(False, RT_SIGNAL_NOTIFY);
- return ret;
-}
-
-/****************************************************************************
- Remove a change notify data structure.
-*****************************************************************************/
-
-static void kernel_remove_notify(void *datap)
-{
- struct change_data *data = (struct change_data *)datap;
- int fd = data->directory_handle;
- if (fd != -1) {
- int i;
- BlockSignals(True, RT_SIGNAL_NOTIFY);
- for (i = 0; i < signals_received; i++) {
- 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));
- }
- data->directory_handle = -1;
- signals_received--;
- break;
- }
- }
- close(fd);
- BlockSignals(False, RT_SIGNAL_NOTIFY);
- }
- SAFE_FREE(data);
- DEBUG(3,("kernel_remove_notify: fd=%d\n", fd));
-}
-
-/****************************************************************************
- Register a change notify request.
-*****************************************************************************/
-
-static void *kernel_register_notify(connection_struct *conn, char *path, uint32 flags)
-{
- struct change_data data;
- int fd;
- unsigned long kernel_flags;
-
- fd = sys_open(path,O_RDONLY, 0);
-
- if (fd == -1) {
- DEBUG(3,("Failed to open directory %s for change notify\n", path));
- return NULL;
- }
-
- if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) {
- DEBUG(3,("Failed to set signal handler for change notify\n"));
- return NULL;
- }
-
- kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion changes everything! */
- if (flags & FILE_NOTIFY_CHANGE_FILE) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE;
- if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY;
- if (flags & FILE_NOTIFY_CHANGE_LAST_ACCESS) kernel_flags |= DN_ACCESS;
- if (flags & FILE_NOTIFY_CHANGE_CREATION) kernel_flags |= DN_CREATE;
- if (flags & FILE_NOTIFY_CHANGE_SECURITY) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB;
- if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE;
-
- if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) {
- DEBUG(3,("Failed to set async flag for change notify\n"));
- return NULL;
- }
-
- data.directory_handle = fd;
-
- DEBUG(3,("kernel change notify on %s (ntflags=0x%x flags=0x%x) fd=%d\n",
- path, (int)flags, (int)kernel_flags, fd));
-
- return (void *)memdup(&data, sizeof(data));
-}
-
-/****************************************************************************
- See if the kernel supports change notify.
-****************************************************************************/
-
-static BOOL kernel_notify_available(void)
-{
- int fd, ret;
- fd = open("/tmp", O_RDONLY);
- if (fd == -1)
- return False; /* uggh! */
- ret = sys_fcntl_long(fd, F_NOTIFY, 0);
- close(fd);
- return ret == 0;
-}
-
-/****************************************************************************
- Setup kernel based change notify.
-****************************************************************************/
-
-struct cnotify_fns *kernel_notify_init(void)
-{
- static struct cnotify_fns cnotify;
- struct sigaction act;
-
- ZERO_STRUCT(act);
-
- act.sa_sigaction = signal_handler;
- act.sa_flags = SA_SIGINFO;
- sigemptyset( &act.sa_mask );
- if (sigaction(RT_SIGNAL_NOTIFY, &act, NULL) != 0) {
- DEBUG(0,("Failed to setup RT_SIGNAL_NOTIFY handler\n"));
- return NULL;
- }
-
- if (!kernel_notify_available())
- return NULL;
-
- cnotify.register_notify = kernel_register_notify;
- cnotify.check_notify = kernel_check_notify;
- cnotify.remove_notify = kernel_remove_notify;
- cnotify.select_time = -1;
- cnotify.notification_fd = -1;
-
- /* the signal can start off blocked due to a bug in bash */
- BlockSignals(False, RT_SIGNAL_NOTIFY);
-
- return &cnotify;
-}
-
-#else
- void notify_kernel_dummy(void);
-
- void notify_kernel_dummy(void) {}
-#endif /* HAVE_KERNEL_CHANGE_NOTIFY */
diff --git a/source/smbd/ntquotas.c b/source/smbd/ntquotas.c
index a824978ecea..e754583312f 100644
--- a/source/smbd/ntquotas.c
+++ b/source/smbd/ntquotas.c
@@ -244,7 +244,7 @@ void destroy_quota_handle(void **pqt_handle)
if (!pqt_handle||!(*pqt_handle))
return;
- qt_handle = (*pqt_handle);
+ qt_handle = (SMB_NTQUOTA_HANDLE *)(*pqt_handle);
if (qt_handle->quota_list)
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 15f427553c8..19710d1dcdd 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -37,6 +37,7 @@ static const char *known_nt_pipes[] = {
"\\lsass",
"\\lsarpc",
"\\winreg",
+ "\\initshutdown",
"\\spoolss",
"\\netdfs",
"\\rpcecho",
@@ -52,7 +53,7 @@ static char *nttrans_realloc(char **ptr, size_t size)
smb_panic("nttrans_realloc() called with NULL ptr\n");
}
- *ptr = SMB_REALLOC(*ptr, size);
+ *ptr = (char *)SMB_REALLOC(*ptr, size);
if(*ptr == NULL) {
return NULL;
}
@@ -67,8 +68,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params,
- int paramsize, char *pdata, int datasize)
+int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error,
+ char *params, int paramsize, char *pdata, int datasize)
{
int data_to_send = datasize;
int params_to_send = paramsize;
@@ -98,7 +99,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
if(params_to_send == 0 && data_to_send == 0) {
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("send_nt_replies: send_smb failed.");
+ exit_server_cleanly("send_nt_replies: send_smb failed.");
}
return 0;
}
@@ -233,7 +234,7 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
/* Send the packet */
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("send_nt_replies: send_smb failed.");
+ exit_server_cleanly("send_nt_replies: send_smb failed.");
}
pp += params_sent_thistime;
@@ -280,10 +281,10 @@ static BOOL saved_short_case_preserve;
Save case semantics.
****************************************************************************/
-static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
+static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
{
if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
- return;
+ return file_attributes;
}
saved_case_sensitive = conn->case_sensitive;
@@ -294,6 +295,8 @@ static void set_posix_case_semantics(connection_struct *conn, uint32 file_attrib
conn->case_sensitive = True;
conn->case_preserve = True;
conn->short_case_preserve = True;
+
+ return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
}
/****************************************************************************
@@ -321,7 +324,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
smb_np_struct *p = NULL;
uint16 vuid = SVAL(inbuf, smb_uid);
int i;
-
+
DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
/* See if it is one we want to handle. */
@@ -350,6 +353,12 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
return(ERROR_DOS(ERRSRV,ERRnofids));
}
+ /* TODO: Add pipe to db */
+
+ if ( !store_pipe_opendb( p ) ) {
+ DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
+ }
+
*ppnum = p->pnum;
return 0;
}
@@ -412,10 +421,14 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
int result;
char *p;
uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
- files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access);
+ files_struct *fsp;
+ NTSTATUS status;
- if (!fsp) {
- return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ status = open_fake_file(conn, fake_file_type, fname, desired_access,
+ &fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
set_message(outbuf,34,0,True);
@@ -425,31 +438,6 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
/* SCVAL(p,0,NO_OPLOCK_RETURN); */
p++;
SSVAL(p,0,fsp->fnum);
-#if 0
- p += 2;
- SIVAL(p,0,smb_action);
- p += 4;
-
- /* Create time. */
- put_long_date(p,c_time);
- p += 8;
- put_long_date(p,sbuf.st_atime); /* access time */
- p += 8;
- put_long_date(p,sbuf.st_mtime); /* write time */
- p += 8;
- put_long_date(p,sbuf.st_mtime); /* change time */
- p += 8;
- SIVAL(p,0,fattr); /* File Attributes. */
- p += 4;
- SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
- p += 8;
- SOFF_T(p,0,file_len);
- p += 8;
- if (flags & EXTENDED_RESPONSE_REQUIRED)
- SSVAL(p,2,0x7);
- p += 4;
- SCVAL(p,0,fsp->is_directory ? 1 : 0);
-#endif
DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
@@ -469,6 +457,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
+ uint32 new_file_attributes;
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
@@ -480,18 +469,20 @@ int reply_ntcreate_and_X(connection_struct *conn,
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
int info = 0;
- BOOL bad_path = False;
files_struct *fsp=NULL;
char *p = NULL;
- time_t c_time;
+ struct timespec c_timespec;
+ struct timespec a_timespec;
+ struct timespec m_timespec;
BOOL extended_oplock_granted = False;
NTSTATUS status;
START_PROFILE(SMBntcreateX);
- DEBUG(10,("reply_ntcreateX: flags = 0x%x, access_mask = 0x%x \
-file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
-create_options = 0x%x root_dir_fid = 0x%x\n",
+ DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
+ "file_attributes = 0x%x, share_access = 0x%x, "
+ "create_disposition = 0x%x create_options = 0x%x "
+ "root_dir_fid = 0x%x\n",
(unsigned int)flags,
(unsigned int)access_mask,
(unsigned int)file_attributes,
@@ -637,38 +628,36 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
* Check if POSIX semantics are wanted.
*/
- set_posix_case_semantics(conn, file_attributes);
+ new_file_attributes = set_posix_case_semantics(conn, file_attributes);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
-
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
/* All file access must go through check_name() */
- if (!check_name(fname,conn)) {
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return ERROR_NT(status);
}
-#if 0
/* This is the correct thing to do (check every time) but can_delete is
expensive (it may have to read the parent directory permissions). So
for now we're not doing it unless we have a strong hint the client
- is really going to delete this file. */
- if (desired_access & DELETE_ACCESS) {
-#else
+ is really going to delete this file. If the client is forcing FILE_CREATE
+ let the filesystem take care of the permissions. */
+
/* Setting FILE_SHARE_DELETE is the hint. */
- if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE)
- && (access_mask & DELETE_ACCESS)) {
-#endif
- status = can_delete(conn, fname, file_attributes, bad_path, True, False);
- /* We're only going to fail here if it's access denied, as that's the
- only error we care about for "can we delete this ?" questions. */
- if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
- NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+
+ if (lp_acl_check_permissions(SNUM(conn))
+ && (create_disposition != FILE_CREATE)
+ && (share_access & FILE_SHARE_DELETE)
+ && (access_mask & DELETE_ACCESS)) {
+ if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
+ !can_delete_file_in_directory(conn, fname)) {
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
@@ -688,18 +677,23 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- fsp = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- &info);
+ new_file_attributes,
+ &info, &fsp);
restore_case_semantics(conn, file_attributes);
- if(!fsp) {
+ if(!NT_STATUS_IS_OK(status)) {
+ if (!use_nt_status() && NT_STATUS_EQUAL(
+ status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+ }
END_PROFILE(SMBntcreateX);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
} else {
/*
@@ -719,15 +713,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
* before issuing an oplock break request to
* our client. JRA. */
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
oplock_request,
- &info);
- if (!fsp) {
+ &info, &fsp);
+ if (!NT_STATUS_IS_OK(status)) {
/* We cheat here. There are two cases we
* care about. One is a directory rename,
* where the NT client will attempt to
@@ -747,7 +741,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
* we handle in the open_file_stat case. JRA.
*/
- if(errno == EISDIR) {
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_FILE_IS_A_DIRECTORY)) {
/*
* Fail the open if it was explicitly a non-directory file.
@@ -760,17 +755,22 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- &info);
+ new_file_attributes,
+ &info, &fsp);
- if(!fsp) {
+ if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
+ if (!use_nt_status() && NT_STATUS_EQUAL(
+ status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+ }
END_PROFILE(SMBntcreateX);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
} else {
@@ -780,7 +780,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
}
}
@@ -873,22 +873,23 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
p += 4;
/* Create time. */
- c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ a_timespec = get_atimespec(&sbuf);
+ m_timespec = get_mtimespec(&sbuf);
if (lp_dos_filetime_resolution(SNUM(conn))) {
- c_time &= ~1;
- sbuf.st_atime &= ~1;
- sbuf.st_mtime &= ~1;
- sbuf.st_mtime &= ~1;
+ dos_filetime_timespec(&c_timespec);
+ dos_filetime_timespec(&a_timespec);
+ dos_filetime_timespec(&m_timespec);
}
- put_long_date(p,c_time);
+ put_long_date_timespec(p, c_timespec);
p += 8;
- put_long_date(p,sbuf.st_atime); /* access time */
+ put_long_date_timespec(p, a_timespec); /* access time */
p += 8;
- put_long_date(p,sbuf.st_mtime); /* write time */
+ put_long_date_timespec(p, m_timespec); /* write time */
p += 8;
- put_long_date(p,sbuf.st_mtime); /* change time */
+ put_long_date_timespec(p, m_timespec); /* change time */
p += 8;
SIVAL(p,0,fattr); /* File Attributes. */
p += 4;
@@ -969,7 +970,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
return -1;
}
@@ -1020,16 +1021,16 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
return NT_STATUS_NO_MEMORY;
}
- if (psd->off_owner_sid==0) {
+ if (psd->owner_sid==0) {
security_info_sent &= ~OWNER_SECURITY_INFORMATION;
}
- if (psd->off_grp_sid==0) {
+ if (psd->group_sid==0) {
security_info_sent &= ~GROUP_SECURITY_INFORMATION;
}
- if (psd->off_sacl==0) {
+ if (psd->sacl==0) {
security_info_sent &= ~SACL_SECURITY_INFORMATION;
}
- if (psd->off_dacl==0) {
+ if (psd->dacl==0) {
security_info_sent &= ~DACL_SECURITY_INFORMATION;
}
@@ -1060,14 +1061,13 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata,
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);
if (!eal) {
return NULL;
}
- DLIST_ADD_END(ea_list_head, eal, tmp);
+ DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
if (next_offset == 0) {
break;
}
@@ -1095,20 +1095,22 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
int info = 0;
- BOOL bad_path = False;
files_struct *fsp = NULL;
char *p = NULL;
BOOL extended_oplock_granted = False;
uint32 flags;
uint32 access_mask;
uint32 file_attributes;
+ uint32 new_file_attributes;
uint32 share_access;
uint32 create_disposition;
uint32 create_options;
uint32 sd_len;
uint32 ea_len;
uint16 root_dir_fid;
- time_t c_time;
+ struct timespec c_timespec;
+ struct timespec a_timespec;
+ struct timespec m_timespec;
struct ea_list *ea_list = NULL;
TALLOC_CTX *ctx = NULL;
char *pdata = NULL;
@@ -1256,55 +1258,48 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Check if POSIX semantics are wanted.
*/
- set_posix_case_semantics(conn, file_attributes);
+ new_file_attributes = set_posix_case_semantics(conn, file_attributes);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
/* All file access must go through check_name() */
- if (!check_name(fname,conn)) {
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return ERROR_NT(status);
}
-#if 0
/* This is the correct thing to do (check every time) but can_delete is
expensive (it may have to read the parent directory permissions). So
for now we're not doing it unless we have a strong hint the client
- is really going to delete this file. */
- if (desired_access & DELETE_ACCESS) {
-#else
+ is really going to delete this file. If the client is forcing FILE_CREATE
+ let the filesystem take care of the permissions. */
+
/* Setting FILE_SHARE_DELETE is the hint. */
- if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) {
-#endif
- status = can_delete(conn, fname, file_attributes, bad_path, True, False);
- /* We're only going to fail here if it's access denied, as that's the
- only error we care about for "can we delete this ?" questions. */
- if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
- NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+
+ if (lp_acl_check_permissions(SNUM(conn))
+ && (create_disposition != FILE_CREATE)
+ && (share_access & FILE_SHARE_DELETE)
+ && (access_mask & DELETE_ACCESS)) {
+ if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
+ !can_delete_file_in_directory(conn, fname)) {
restore_case_semantics(conn, file_attributes);
- return ERROR_NT(status);
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
}
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);
+ ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata,
+ ea_len);
if (!ea_list ) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1318,7 +1313,6 @@ 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);
}
@@ -1331,16 +1325,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* CreateDirectory() call.
*/
- fsp = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- &info);
- if(!fsp) {
- talloc_destroy(ctx);
+ new_file_attributes,
+ &info, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
} else {
@@ -1349,17 +1343,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Ordinary file case.
*/
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
oplock_request,
- &info);
+ &info, &fsp);
- if (!fsp) {
- if(errno == EISDIR) {
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_FILE_IS_A_DIRECTORY)) {
/*
* Fail the open if it was explicitly a non-directory file.
@@ -1371,25 +1366,24 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- &info);
- if(!fsp) {
- talloc_destroy(ctx);
+ new_file_attributes,
+ &info, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
} else {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
}
}
@@ -1424,7 +1418,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (ea_len && (info == FILE_WAS_CREATED)) {
status = set_ea(conn, fsp, fname, ea_list);
- talloc_destroy(ctx);
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp,ERROR_CLOSE);
restore_case_semantics(conn, file_attributes);
@@ -1488,8 +1481,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
p = params;
if (extended_oplock_granted) {
- SCVAL(p,0, BATCH_OPLOCK_RETURN);
- } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
+ if (flags & REQUEST_BATCH_OPLOCK) {
+ SCVAL(p,0, BATCH_OPLOCK_RETURN);
+ } else {
+ SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN);
+ }
+ } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
} else {
SCVAL(p,0,NO_OPLOCK_RETURN);
@@ -1506,22 +1503,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
p += 8;
/* Create time. */
- c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ a_timespec = get_atimespec(&sbuf);
+ m_timespec = get_mtimespec(&sbuf);
if (lp_dos_filetime_resolution(SNUM(conn))) {
- c_time &= ~1;
- sbuf.st_atime &= ~1;
- sbuf.st_mtime &= ~1;
- sbuf.st_mtime &= ~1;
+ dos_filetime_timespec(&c_timespec);
+ dos_filetime_timespec(&a_timespec);
+ dos_filetime_timespec(&m_timespec);
}
- put_long_date(p,c_time);
+ put_long_date_timespec(p, c_timespec); /* create time. */
p += 8;
- put_long_date(p,sbuf.st_atime); /* access time */
+ put_long_date_timespec(p, a_timespec); /* access time */
p += 8;
- put_long_date(p,sbuf.st_mtime); /* write time */
+ put_long_date_timespec(p, m_timespec); /* write time */
p += 8;
- put_long_date(p,sbuf.st_mtime); /* change time */
+ put_long_date_timespec(p, m_timespec); /* change time */
p += 8;
SIVAL(p,0,fattr); /* File Attributes. */
p += 4;
@@ -1538,7 +1536,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
return -1;
}
@@ -1573,8 +1571,6 @@ int reply_ntcancel(connection_struct *conn,
static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
{
- BOOL bad_path_oldname = False;
- BOOL bad_path_newname = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
pstring last_component_newname;
@@ -1582,38 +1578,27 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
uint32 fattr;
int info;
SMB_OFF_T ret=-1;
- int close_ret;
NTSTATUS status = NT_STATUS_OK;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- /* No wildcards. */
- if (ms_has_wild(newname) || ms_has_wild(oldname)) {
- return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- }
-
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
-
- unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
- if (bad_path_oldname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- /* Quick check for "." and ".." */
- if (last_component_oldname[0] == '.') {
- if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Source must already exist. */
if (!VALID_STAT(sbuf1)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (!check_name(oldname,conn)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Ensure attributes match. */
@@ -1622,16 +1607,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
return NT_STATUS_NO_SUCH_FILE;
}
- unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
- if (bad_path_newname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_newname[0] == '.') {
- if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Disallow if newname already exists. */
@@ -1639,8 +1617,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (!check_name(newname,conn)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* No links from a directory. */
@@ -1649,45 +1628,36 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
}
/* Ensure this is within the share. */
- if (!reduce_name(conn, oldname) != 0) {
- return NT_STATUS_ACCESS_DENIED;
+ status = reduce_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
- fsp1 = open_file_ntcreate(conn,oldname,&sbuf1,
+ status = open_file_ntcreate(conn,oldname,&sbuf1,
FILE_READ_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
0, /* No create options. */
FILE_ATTRIBUTE_NORMAL,
NO_OPLOCK,
- &info);
+ &info, &fsp1);
- if (!fsp1) {
- status = get_saved_ntstatus();
- if (NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_ACCESS_DENIED;
- }
- set_saved_ntstatus(NT_STATUS_OK);
+ if (!NT_STATUS_IS_OK(status)) {
return status;
}
- fsp2 = open_file_ntcreate(conn,newname,&sbuf2,
- FILE_WRITE_DATA, /* Write-only. */
+ status = open_file_ntcreate(conn,newname,&sbuf2,
+ FILE_WRITE_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_CREATE,
0, /* No create options. */
fattr,
NO_OPLOCK,
- &info);
+ &info, &fsp2);
- if (!fsp2) {
- status = get_saved_ntstatus();
- if (NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_ACCESS_DENIED;
- }
- set_saved_ntstatus(NT_STATUS_OK);
+ if (!NT_STATUS_IS_OK(status)) {
close_file(fsp1,ERROR_CLOSE);
return status;
}
@@ -1707,19 +1677,19 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
/* Ensure the modtime is set correctly on the destination file. */
fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
- close_ret = close_file(fsp2,NORMAL_CLOSE);
+ status = close_file(fsp2,NORMAL_CLOSE);
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
- file_set_dosmode(conn, newname, fattr, &sbuf2, True);
+ file_set_dosmode(conn, newname, fattr, &sbuf2,
+ parent_dirname(newname));
if (ret < (SMB_OFF_T)sbuf1.st_size) {
return NT_STATUS_DISK_FULL;
}
- if (close_ret != 0) {
- status = map_nt_error_from_unix(close_ret);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
nt_errstr(status), oldname, newname));
}
@@ -1738,14 +1708,15 @@ int reply_ntrename(connection_struct *conn,
pstring newname;
char *p;
NTSTATUS status;
- BOOL path_contains_wcard = False;
+ BOOL path1_contains_wcard = False;
+ BOOL path2_contains_wcard = False;
uint32 attrs = SVAL(inbuf,smb_vwv0);
uint16 rename_type = SVAL(inbuf,smb_vwv1);
START_PROFILE(SMBntrename);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@@ -1763,7 +1734,7 @@ int reply_ntrename(connection_struct *conn,
}
p++;
- p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@@ -1776,13 +1747,18 @@ int reply_ntrename(connection_struct *conn,
switch(rename_type) {
case RENAME_FLAG_RENAME:
- status = rename_internals(conn, oldname, newname, attrs, False, path_contains_wcard);
+ status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard);
break;
case RENAME_FLAG_HARD_LINK:
- status = hardlink_internals(conn, oldname, newname);
+ if (path1_contains_wcard || path2_contains_wcard) {
+ /* No wildcards. */
+ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ } else {
+ status = hardlink_internals(conn, oldname, newname);
+ }
break;
case RENAME_FLAG_COPY:
- if (path_contains_wcard) {
+ if (path1_contains_wcard || path2_contains_wcard) {
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
@@ -1806,11 +1782,6 @@ int reply_ntrename(connection_struct *conn,
return ERROR_NT(status);
}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
- process_pending_change_notify_queue((time_t)0);
outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBntrename);
@@ -1822,21 +1793,29 @@ int reply_ntrename(connection_struct *conn,
don't allow a directory to be opened.
****************************************************************************/
-static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
- uint16 **ppsetup, uint32 setup_count,
- char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count, uint32 max_data_count)
+static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
+ char *outbuf, int length,
+ int bufsize,
+ uint16 **ppsetup, uint32 setup_count,
+ char **ppparams,
+ uint32 parameter_count,
+ char **ppdata, uint32 data_count,
+ uint32 max_data_count,
+ uint32 max_param_count)
{
uint16 *setup = *ppsetup;
files_struct *fsp;
- uint32 flags;
+ uint32 filter;
+ NTSTATUS status;
+ BOOL recursive;
if(setup_count < 6) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
}
fsp = file_fsp((char *)setup,4);
- flags = IVAL(setup, 0);
+ filter = IVAL(setup, 0);
+ recursive = (SVAL(setup, 6) != 0) ? True : False;
DEBUG(3,("call_nt_transact_notify_change\n"));
@@ -1844,16 +1823,65 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRDOS,ERRbadfid);
}
+ {
+ char *filter_string;
+
+ if (!(filter_string = notify_filter_string(NULL, filter))) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ DEBUG(3,("call_nt_transact_notify_change: notify change "
+ "called on %s, filter = %s, recursive = %d\n",
+ fsp->fsp_name, filter_string, recursive));
+
+ TALLOC_FREE(filter_string);
+ }
+
if((!fsp->is_directory) || (conn != fsp->conn)) {
- return ERROR_DOS(ERRDOS,ERRbadfid);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- if (!change_notify_set(inbuf, fsp, conn, flags)) {
- return(UNIXERROR(ERRDOS,ERRbadfid));
+ if (fsp->notify == NULL) {
+
+ status = change_notify_create(fsp, filter, recursive);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("change_notify_create returned %s\n",
+ nt_errstr(status)));
+ return ERROR_NT(status);
+ }
}
- DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \
-name = %s\n", fsp->fsp_name ));
+ if (fsp->notify->num_changes != 0) {
+
+ /*
+ * We've got changes pending, respond immediately
+ */
+
+ /*
+ * TODO: write a torture test to check the filtering behaviour
+ * here.
+ */
+
+ change_notify_reply(inbuf, max_param_count,
+ fsp->notify);
+
+ /*
+ * change_notify_reply() above has independently sent its
+ * results
+ */
+ return -1;
+ }
+
+ /*
+ * No changes pending, queue the request
+ */
+
+ status = change_notify_add_request(inbuf, max_param_count, filter,
+ recursive, fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
return -1;
}
@@ -1874,14 +1902,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
BOOL path_contains_wcard = False;
NTSTATUS status;
- if(parameter_count < 4) {
+ if(parameter_count < 5) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
}
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
- srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, &path_contains_wcard);
+ srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -1900,18 +1928,11 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
/*
* Rename was successful.
*/
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
fsp->fsp_name, new_name));
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
-
- process_pending_change_notify_queue((time_t)0);
-
return -1;
}
@@ -1995,8 +2016,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
if(max_data_count < sd_size) {
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
- params, 4, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
+ params, 4, *ppdata, 0);
talloc_destroy(mem_ctx);
return -1;
}
@@ -2044,7 +2065,8 @@ security descriptor.\n"));
talloc_destroy(mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data,
+ (int)sd_size);
return -1;
}
@@ -2090,7 +2112,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
done:
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
}
@@ -2136,7 +2158,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
so we can know if we need to pre-allocate or not */
DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ 0);
return -1;
case FSCTL_0x000900C0:
@@ -2145,7 +2168,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ 0);
return -1;
case FSCTL_GET_REPARSE_POINT:
@@ -2154,7 +2178,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
return -1;
case FSCTL_SET_REPARSE_POINT:
@@ -2163,7 +2188,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
return -1;
case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
@@ -2276,7 +2302,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
talloc_destroy(shadow_data->mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ pdata, data_count);
return -1;
}
@@ -2328,7 +2355,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
/* this works for now... */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ NULL, 0);
return -1;
}
default:
@@ -2368,7 +2396,6 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
SMB_NTQUOTA_STRUCT qt;
SMB_NTQUOTA_LIST *tmp_list;
SMB_NTQUOTA_HANDLE *qt_handle = NULL;
- extern struct current_user current_user;
ZERO_STRUCT(qt);
@@ -2395,7 +2422,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
return ERROR_NT(NT_STATUS_INVALID_HANDLE);
}
- /* the NULL pointer cheking for fsp->fake_file_handle->pd
+ /* the NULL pointer checking for fsp->fake_file_handle->pd
* is done by CHECK_NTQUOTA_HANDLE_OK()
*/
qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd;
@@ -2595,7 +2622,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
break;
}
- send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len);
+ send_nt_replies(outbuf, bufsize, nt_status, params, param_len,
+ pdata, data_len);
return -1;
}
@@ -2712,7 +2740,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRSRV,ERRerror);
}
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len,
+ pdata, data_len);
return -1;
}
@@ -2732,99 +2761,101 @@ static int handle_nttrans(connection_struct *conn,
switch(state->call) {
case NT_TRANSACT_CREATE:
{
- START_PROFILE_NESTED(NT_transact_create);
+ START_PROFILE(NT_transact_create);
outsize = call_nt_transact_create(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(NT_transact_create);
+ END_PROFILE(NT_transact_create);
break;
}
case NT_TRANSACT_IOCTL:
{
- START_PROFILE_NESTED(NT_transact_ioctl);
+ START_PROFILE(NT_transact_ioctl);
outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_ioctl);
+ END_PROFILE(NT_transact_ioctl);
break;
}
case NT_TRANSACT_SET_SECURITY_DESC:
{
- START_PROFILE_NESTED(NT_transact_set_security_desc);
+ START_PROFILE(NT_transact_set_security_desc);
outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_set_security_desc);
+ END_PROFILE(NT_transact_set_security_desc);
break;
}
case NT_TRANSACT_NOTIFY_CHANGE:
{
- START_PROFILE_NESTED(NT_transact_notify_change);
- outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
- size, bufsize,
- &state->setup, state->setup_count,
- &state->param, state->total_param,
- &state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_notify_change);
+ START_PROFILE(NT_transact_notify_change);
+ outsize = call_nt_transact_notify_change(
+ conn, inbuf, outbuf, size, bufsize,
+ &state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data,
+ state->max_data_return,
+ state->max_param_return);
+ END_PROFILE(NT_transact_notify_change);
break;
}
case NT_TRANSACT_RENAME:
{
- START_PROFILE_NESTED(NT_transact_rename);
+ START_PROFILE(NT_transact_rename);
outsize = call_nt_transact_rename(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_rename);
+ END_PROFILE(NT_transact_rename);
break;
}
case NT_TRANSACT_QUERY_SECURITY_DESC:
{
- START_PROFILE_NESTED(NT_transact_query_security_desc);
+ START_PROFILE(NT_transact_query_security_desc);
outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_query_security_desc);
+ END_PROFILE(NT_transact_query_security_desc);
break;
}
#ifdef HAVE_SYS_QUOTAS
case NT_TRANSACT_GET_USER_QUOTA:
{
- START_PROFILE_NESTED(NT_transact_get_user_quota);
+ START_PROFILE(NT_transact_get_user_quota);
outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_get_user_quota);
+ END_PROFILE(NT_transact_get_user_quota);
break;
}
case NT_TRANSACT_SET_USER_QUOTA:
{
- START_PROFILE_NESTED(NT_transact_set_user_quota);
+ START_PROFILE(NT_transact_set_user_quota);
outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
size, bufsize,
&state->setup, state->setup_count,
&state->param, state->total_param,
&state->data, state->total_data, state->max_data_return);
- END_PROFILE_NESTED(NT_transact_set_user_quota);
+ END_PROFILE(NT_transact_set_user_quota);
break;
}
#endif /* HAVE_SYS_QUOTAS */
@@ -2869,7 +2900,7 @@ int reply_nttrans(connection_struct *conn,
return ERROR_NT(result);
}
- if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
END_PROFILE(SMBnttrans);
return ERROR_DOS(ERRSRV,ERRaccess);
}
@@ -2883,9 +2914,11 @@ int reply_nttrans(connection_struct *conn,
state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
state->param = NULL;
state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);
+ state->max_param_return = IVAL(inbuf,smb_nt_MaxParameterCount);
/* setup count is in *words* */
state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount);
+ state->setup = NULL;
state->call = function_code;
/*
@@ -2912,7 +2945,7 @@ int reply_nttrans(connection_struct *conn,
if (state->total_data) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- if ((state->data = SMB_MALLOC(state->total_data)) == NULL) {
+ if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) {
DEBUG(0,("reply_nttrans: data malloc fail for %u "
"bytes !\n", (unsigned int)state->total_data));
TALLOC_FREE(state);
@@ -2931,7 +2964,7 @@ int reply_nttrans(connection_struct *conn,
if (state->total_param) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- if ((state->param = SMB_MALLOC(state->total_param)) == NULL) {
+ if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) {
DEBUG(0,("reply_nttrans: param malloc fail for %u "
"bytes !\n", (unsigned int)state->total_param));
SAFE_FREE(state->data);
@@ -2954,7 +2987,7 @@ int reply_nttrans(connection_struct *conn,
if(state->setup_count > 0) {
DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
state->setup_count));
- state->setup = TALLOC(state, state->setup_count);
+ state->setup = (uint16 *)TALLOC(state, state->setup_count);
if (state->setup == NULL) {
DEBUG(0,("reply_nttrans : Out of memory\n"));
SAFE_FREE(state->data);
diff --git a/source/smbd/open.c b/source/smbd/open.c
index bf18b089a3e..13ec9f952fe 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -38,38 +38,43 @@ struct deferred_open_record {
fd support routines - attempt to do a dos_open.
****************************************************************************/
-static int fd_open(struct connection_struct *conn,
- const char *fname,
- int flags,
- mode_t mode)
+static NTSTATUS fd_open(struct connection_struct *conn,
+ const char *fname,
+ files_struct *fsp,
+ int flags,
+ mode_t mode)
{
- int fd;
+ NTSTATUS status = NT_STATUS_OK;
+
#ifdef O_NOFOLLOW
if (!lp_symlinks(SNUM(conn))) {
flags |= O_NOFOLLOW;
}
#endif
- fd = SMB_VFS_OPEN(conn,fname,flags,mode);
+ fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
+ if (fsp->fh->fd == -1) {
+ status = map_nt_error_from_unix(errno);
+ }
- DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname,
- flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" ));
+ DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
+ fname, flags, (int)mode, fsp->fh->fd,
+ (fsp->fh->fd == -1) ? strerror(errno) : "" ));
- return fd;
+ return status;
}
/****************************************************************************
Close the file associated with a fsp.
****************************************************************************/
-int fd_close(struct connection_struct *conn,
- files_struct *fsp)
+NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp)
{
if (fsp->fh->fd == -1) {
- return 0; /* What we used to call a stat open. */
+ return NT_STATUS_OK; /* What we used to call a stat open. */
}
if (fsp->fh->ref_count > 1) {
- return 0; /* Shared handle. Only close last reference. */
+ return NT_STATUS_OK; /* Shared handle. Only close last reference. */
}
return fd_close_posix(conn, fsp);
}
@@ -79,115 +84,129 @@ int fd_close(struct connection_struct *conn,
Do this by fd if possible.
****************************************************************************/
-void change_owner_to_parent(connection_struct *conn,
- files_struct *fsp,
- const char *fname,
- SMB_STRUCT_STAT *psbuf)
+static void change_file_owner_to_parent(connection_struct *conn,
+ const char *inherit_from_dir,
+ files_struct *fsp)
{
- const char *parent_path = parent_dirname(fname);
SMB_STRUCT_STAT parent_st;
int ret;
- ret = SMB_VFS_STAT(conn, parent_path, &parent_st);
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
if (ret == -1) {
- DEBUG(0,("change_owner_to_parent: failed to stat parent "
+ DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- parent_path, strerror(errno) ));
+ inherit_from_dir, strerror(errno) ));
return;
}
- if (fsp && fsp->fh->fd != -1) {
- become_root();
- ret = SMB_VFS_FCHOWN(fsp, fsp->fh->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) ));
- }
+ become_root();
+ ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1);
+ unbecome_root();
+ if (ret == -1) {
+ DEBUG(0,("change_file_owner_to_parent: failed to fchown "
+ "file %s to parent directory uid %u. Error "
+ "was %s\n", fsp->fsp_name,
+ (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 ));
+ DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
+ "parent directory uid %u.\n", fsp->fsp_name,
+ (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;
- }
+static void change_dir_owner_to_parent(connection_struct *conn,
+ const char *inherit_from_dir,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ pstring saved_dir;
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT parent_st;
+ int ret;
- /* 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;
- }
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ if (ret == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
+ "directory %s. Error was %s\n",
+ inherit_from_dir, strerror(errno) ));
+ return;
+ }
- 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;
- }
+ /* 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.
+ */
- /* 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;
- }
+ if (!vfs_GetWd(conn,saved_dir)) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to get "
+ "current working directory\n"));
+ return;
+ }
- 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;
- }
+ /* Chdir into the new path. */
+ if (vfs_ChDir(conn, fname) == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to change "
+ "current working directory to %s. Error "
+ "was %s\n", fname, 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 ));
+ if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to stat "
+ "directory '.' (%s) Error was %s\n",
+ fname, strerror(errno)));
+ goto out;
+ }
- 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_dir_owner_to_parent: "
+ "device/inode/mode on directory %s changed. "
+ "Refusing to chown !\n", fname ));
+ goto out;
+ }
- vfs_ChDir(conn,saved_dir);
+ become_root();
+ ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
+ unbecome_root();
+ if (ret == -1) {
+ DEBUG(10,("change_dir_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_dir_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);
}
/****************************************************************************
Open a file.
****************************************************************************/
-static BOOL open_file(files_struct *fsp,
- connection_struct *conn,
- const char *fname,
- SMB_STRUCT_STAT *psbuf,
- int flags,
- mode_t unx_mode,
- uint32 access_mask, /* client requested access mask. */
- uint32 open_access_mask) /* what we're actually using in the open. */
+static NTSTATUS open_file(files_struct *fsp,
+ connection_struct *conn,
+ const char *parent_dir,
+ const char *name,
+ const char *path,
+ SMB_STRUCT_STAT *psbuf,
+ int flags,
+ mode_t unx_mode,
+ uint32 access_mask, /* client requested access mask. */
+ uint32 open_access_mask) /* what we're actually using in the open. */
{
+ NTSTATUS status = NT_STATUS_OK;
int accmode = (flags & O_ACCMODE);
int local_flags = flags;
BOOL file_existed = VALID_STAT(*psbuf);
@@ -210,8 +229,8 @@ static BOOL open_file(files_struct *fsp,
if (!CAN_WRITE(conn)) {
/* It's a read-only share - fail if we wanted to write. */
if(accmode != O_RDONLY) {
- DEBUG(3,("Permission denied opening %s\n",fname));
- return False;
+ DEBUG(3,("Permission denied opening %s\n", path));
+ return NT_STATUS_ACCESS_DENIED;
} else if(flags & O_CREAT) {
/* We don't want to write - but we must make sure that
O_CREAT doesn't create the file if we have write
@@ -236,7 +255,7 @@ static BOOL open_file(files_struct *fsp,
if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
DEBUG(10,("open_file: truncate requested on read-only open "
- "for file %s\n",fname ));
+ "for file %s\n", path));
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
}
@@ -265,23 +284,35 @@ static BOOL open_file(files_struct *fsp,
/* Don't create files with Microsoft wildcard characters. */
if ((local_flags & O_CREAT) && !file_existed &&
- ms_has_wild(fname)) {
- set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID);
- return False;
+ ms_has_wild(path)) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
/* Actually do the open */
- fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode);
- if (fsp->fh->fd == -1) {
+ status = fd_open(conn, path, fsp, local_flags, unx_mode);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
"(flags=%d)\n",
- fname,strerror(errno),local_flags,flags));
- return False;
+ path,nt_errstr(status),local_flags,flags));
+ return status;
}
- /* Inherit the ACL if the file was created. */
if ((local_flags & O_CREAT) && !file_existed) {
- inherit_access_acl(conn, fname, unx_mode);
+
+ /* Inherit the ACL if required */
+ if (lp_inherit_perms(SNUM(conn))) {
+ inherit_access_acl(conn, parent_dir, path,
+ unx_mode);
+ }
+
+ /* Change the owner if required. */
+ if (lp_inherit_owner(SNUM(conn))) {
+ change_file_owner_to_parent(conn, parent_dir,
+ fsp);
+ }
+
+ notify_fname(conn, NOTIFY_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME, path);
}
} else {
@@ -292,20 +323,21 @@ static BOOL open_file(files_struct *fsp,
int ret;
if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, fname, psbuf);
+ ret = SMB_VFS_STAT(conn, path, psbuf);
} else {
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
/* If we have an fd, this stat should succeed. */
if (ret == -1) {
DEBUG(0,("Error doing fstat on open file %s "
- "(%s)\n", fname,strerror(errno) ));
+ "(%s)\n", path,strerror(errno) ));
}
}
/* For a non-io open, this stat failing means file not found. JRA */
if (ret == -1) {
+ status = map_nt_error_from_unix(errno);
fd_close(conn, fsp);
- return False;
+ return status;
}
}
@@ -318,7 +350,7 @@ static BOOL open_file(files_struct *fsp,
if(S_ISDIR(psbuf->st_mode)) {
fd_close(conn, fsp);
errno = EISDIR;
- return False;
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
}
fsp->mode = psbuf->st_mode;
@@ -331,7 +363,8 @@ static BOOL open_file(files_struct *fsp,
if (!CAN_WRITE(conn)) {
fsp->can_write = False;
} else {
- fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
+ fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
+ True : False;
}
fsp->print_file = False;
fsp->modified = False;
@@ -339,20 +372,21 @@ static BOOL open_file(files_struct *fsp,
fsp->is_directory = False;
fsp->is_stat = False;
if (conn->aio_write_behind_list &&
- is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
+ is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) {
fsp->aio_write_behind = True;
}
- string_set(&fsp->fsp_name,fname);
+ string_set(&fsp->fsp_name, path);
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
- *current_user_info.smb_name ? current_user_info.smb_name : conn->user,fsp->fsp_name,
+ *current_user_info.smb_name ?
+ current_user_info.smb_name : conn->user,fsp->fsp_name,
BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
conn->num_files_open + 1));
errno = 0;
- return True;
+ return NT_STATUS_OK;
}
/*******************************************************************
@@ -469,8 +503,8 @@ static void validate_my_share_entries(int num,
if (is_deferred_open_entry(share_entry) &&
!open_was_deferred(share_entry->op_mid)) {
pstring str;
- DEBUG(0, ("Got a deferred entry without a request: "
- "PANIC: %s\n", share_mode_str(num, share_entry)));
+ pstr_sprintf(str, "Got a deferred entry without a request: "
+ "PANIC: %s\n", share_mode_str(num, share_entry));
smb_panic(str);
}
@@ -610,15 +644,17 @@ static BOOL is_delete_request(files_struct *fsp) {
*/
static BOOL delay_for_oplocks(struct share_mode_lock *lck,
- files_struct *fsp,
- int pass_number,
- int oplock_request)
+ files_struct *fsp,
+ int pass_number,
+ int oplock_request)
{
int i;
struct share_mode_entry *exclusive = NULL;
BOOL valid_entry = False;
BOOL delay_it = False;
BOOL have_level2 = False;
+ NTSTATUS status;
+ char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
if (oplock_request & INTERNAL_OPEN_ONLY) {
fsp->oplock_type = NO_OPLOCK;
@@ -682,34 +718,37 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck,
fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
}
- if (delay_it) {
- BOOL ret;
- char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
+ if (!delay_it) {
+ return False;
+ }
+
+ /*
+ * Send a break message to the oplock holder and delay the open for
+ * our client.
+ */
- DEBUG(10, ("Sending break request to PID %s\n",
- procid_str_static(&exclusive->pid)));
- exclusive->op_mid = get_current_mid();
+ DEBUG(10, ("Sending break request to PID %s\n",
+ procid_str_static(&exclusive->pid)));
+ exclusive->op_mid = get_current_mid();
- /* Create the message. */
- share_mode_entry_to_message(msg, exclusive);
+ /* Create the message. */
+ share_mode_entry_to_message(msg, exclusive);
- /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't
- want this set in the share mode struct pointed to by lck. */
+ /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We
+ don't want this set in the share mode struct pointed to by lck. */
- if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
- SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
- }
+ if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
+ SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
+ }
- become_root();
- ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
- msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
- unbecome_root();
- if (!ret) {
- DEBUG(3, ("Could not send oplock break message\n"));
- }
+ status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("Could not send oplock break message: %s\n",
+ nt_errstr(status)));
}
- return delay_it;
+ return True;
}
static BOOL request_timed_out(struct timeval request_time,
@@ -773,40 +812,18 @@ static void defer_open(struct share_mode_lock *lck,
srv_defer_sign_response(mid);
}
-/****************************************************************************
- Set a kernel flock on a file for NFS interoperability.
- This requires a patch to Linux.
-****************************************************************************/
-
-static void kernel_flock(files_struct *fsp, uint32 share_mode)
-{
-#if HAVE_KERNEL_SHARE_MODES
- int kernel_mode = 0;
- if (share_mode == FILE_SHARE_WRITE) {
- kernel_mode = LOCK_MAND|LOCK_WRITE;
- } else if (share_mode == FILE_SHARE_READ) {
- kernel_mode = LOCK_MAND|LOCK_READ;
- } else if (share_mode == FILE_SHARE_NONE) {
- kernel_mode = LOCK_MAND;
- }
- if (kernel_mode) {
- flock(fsp->fh->fd, kernel_mode);
- }
-#endif
- ;
-}
/****************************************************************************
On overwrite open ensure that the attributes match.
****************************************************************************/
static BOOL open_match_attributes(connection_struct *conn,
- const char *path,
- uint32 old_dos_attr,
- uint32 new_dos_attr,
- mode_t existing_unx_mode,
- mode_t new_unx_mode,
- mode_t *returned_unx_mode)
+ const char *path,
+ uint32 old_dos_attr,
+ uint32 new_dos_attr,
+ mode_t existing_unx_mode,
+ mode_t new_unx_mode,
+ mode_t *returned_unx_mode)
{
uint32 noarch_old_dos_attr, noarch_new_dos_attr;
@@ -898,8 +915,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn,
}
/* We need to duplicate this fsp. */
- dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options);
- if (!dup_fsp) {
+ if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access,
+ create_options, &dup_fsp))) {
return NULL;
}
@@ -911,10 +928,10 @@ static files_struct *fcb_or_dos_open(connection_struct *conn,
****************************************************************************/
BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func,
- uint32 *paccess_mask,
- uint32 *pshare_mode,
- uint32 *pcreate_disposition,
- uint32 *pcreate_options)
+ uint32 *paccess_mask,
+ uint32 *pshare_mode,
+ uint32 *pcreate_disposition,
+ uint32 *pcreate_options)
{
uint32 access_mask;
uint32 share_mode;
@@ -1085,25 +1102,27 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ
Open a file with a share mode.
****************************************************************************/
-files_struct *open_file_ntcreate(connection_struct *conn,
- const char *fname,
- SMB_STRUCT_STAT *psbuf,
- uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */
- uint32 share_access, /* share constants (FILE_SHARE_READ etc). */
- uint32 create_disposition, /* FILE_OPEN_IF etc. */
- uint32 create_options, /* options such as delete on close. */
- uint32 new_dos_attributes, /* attributes used for new file. */
- int oplock_request, /* internal Samba oplock codes. */
- /* Information (FILE_EXISTS etc.) */
- int *pinfo)
+NTSTATUS open_file_ntcreate(connection_struct *conn,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */
+ uint32 share_access, /* share constants (FILE_SHARE_READ etc) */
+ uint32 create_disposition, /* FILE_OPEN_IF etc. */
+ uint32 create_options, /* options such as delete on close. */
+ uint32 new_dos_attributes, /* attributes used for new file. */
+ int oplock_request, /* internal Samba oplock codes. */
+ /* Information (FILE_EXISTS etc.) */
+ int *pinfo,
+ files_struct **result)
{
int flags=0;
int flags2=0;
BOOL file_existed = VALID_STAT(*psbuf);
BOOL def_acl = False;
+ BOOL posix_open = False;
SMB_DEV_T dev = 0;
SMB_INO_T inode = 0;
- BOOL fsp_open = False;
+ NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
files_struct *fsp = NULL;
mode_t new_unx_mode = (mode_t)0;
mode_t unx_mode = (mode_t)0;
@@ -1115,6 +1134,9 @@ files_struct *open_file_ntcreate(connection_struct *conn,
struct share_mode_lock *lck = NULL;
uint32 open_access_mask = access_mask;
NTSTATUS status;
+ int ret_flock;
+ char *parent_dir;
+ const char *newname;
if (conn->printer) {
/*
@@ -1128,12 +1150,24 @@ files_struct *open_file_ntcreate(connection_struct *conn,
DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
- return print_fsp_open(conn, fname);
+ return print_fsp_open(conn, fname, result);
}
- /* We add aARCH to this as this mode is only used if the file is
- * created new. */
- unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True);
+ if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir,
+ &newname)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ posix_open = True;
+ unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
+ new_dos_attributes = 0;
+ } else {
+ /* We add aARCH to this as this mode is only used if the file is
+ * created new. */
+ unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname,
+ parent_dir);
+ }
DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
"access_mask=0x%x share_access=0x%x "
@@ -1166,13 +1200,16 @@ files_struct *open_file_ntcreate(connection_struct *conn,
remove_deferred_open_smb_message(mid);
}
- if (!check_name(fname,conn)) {
- return NULL;
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
- if (file_existed) {
- existing_dos_attributes = dos_mode(conn, fname, psbuf);
+ if (!posix_open) {
+ new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
+ if (file_existed) {
+ existing_dos_attributes = dos_mode(conn, fname, psbuf);
+ }
}
/* ignore any oplock requests if oplocks are disabled */
@@ -1185,12 +1222,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
/* this is for OS/2 long file names - say we don't support them */
if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
/* OS/2 Workplace shell fix may be main code stream in a later
- * release. */
- set_saved_error_triple(ERRDOS, ERRcannotopen,
- NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ * release. */
DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
"supported.\n"));
- return NULL;
+ if (use_nt_status()) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ return NT_STATUS_DOS(ERRDOS, ERRcannotopen);
}
switch( create_disposition ) {
@@ -1218,9 +1256,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
DEBUG(5,("open_file_ntcreate: FILE_OPEN "
"requested for file %s and file "
"doesn't exist.\n", fname ));
- set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
errno = ENOENT;
- return NULL;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
break;
@@ -1231,9 +1268,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
"requested for file %s and file "
"doesn't exist.\n", fname ));
- set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
errno = ENOENT;
- return NULL;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
flags2 |= O_TRUNC;
break;
@@ -1250,7 +1286,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
} else {
errno = EEXIST;
}
- return NULL;
+ return map_nt_error_from_unix(errno);
}
flags2 |= (O_CREAT|O_EXCL);
break;
@@ -1262,14 +1298,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
break;
default:
- set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
- return NULL;
+ return NT_STATUS_INVALID_PARAMETER;
}
/* We only care about matching attributes on file exists and
* overwrite. */
- if (file_existed && ((create_disposition == FILE_OVERWRITE) ||
+ if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) ||
(create_disposition == FILE_OVERWRITE_IF))) {
if (!open_match_attributes(conn, fname,
existing_dos_attributes,
@@ -1282,7 +1317,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
(unsigned int)psbuf->st_mode,
(unsigned int)unx_mode ));
errno = EACCES;
- return NULL;
+ return NT_STATUS_ACCESS_DENIED;
}
}
@@ -1311,7 +1346,15 @@ files_struct *open_file_ntcreate(connection_struct *conn,
*/
if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) {
- flags = O_RDWR;
+ /* DENY_DOS opens are always underlying read-write on the
+ file handle, no matter what the requested access mask
+ says. */
+ if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) ||
+ access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) {
+ flags = O_RDWR;
+ } else {
+ flags = O_WRONLY;
+ }
} else {
flags = O_RDONLY;
}
@@ -1326,7 +1369,11 @@ files_struct *open_file_ntcreate(connection_struct *conn,
}
#endif /* O_SYNC */
- if (!CAN_WRITE(conn)) {
+ if (posix_open & (access_mask & FILE_APPEND_DATA)) {
+ flags2 |= O_APPEND;
+ }
+
+ if (!posix_open && !CAN_WRITE(conn)) {
/*
* We should really return a permission denied error if either
* O_CREAT or O_TRUNC are set, but for compatibility with
@@ -1344,21 +1391,24 @@ files_struct *open_file_ntcreate(connection_struct *conn,
DEBUG(5,("open_file_ntcreate: write access requested for "
"file %s on read only %s\n",
fname, !CAN_WRITE(conn) ? "share" : "file" ));
- set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
errno = EACCES;
- return NULL;
+ return NT_STATUS_ACCESS_DENIED;
}
- fsp = file_new(conn);
- if(!fsp) {
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
}
fsp->dev = psbuf->st_dev;
fsp->inode = psbuf->st_ino;
fsp->share_access = share_access;
fsp->fh->private_options = create_options;
- fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */
+ fsp->access_mask = open_access_mask; /* We change this to the
+ * requested access_mask after
+ * the open is done. */
+ fsp->posix_open = posix_open;
+
/* Ensure no SAMBA_PRIVATE bits can be set. */
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
@@ -1371,14 +1421,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
inode = psbuf->st_ino;
lck = get_share_mode_lock(NULL, dev, inode,
- conn->connectpath,
- fname);
+ conn->connectpath,
+ fname);
if (lck == NULL) {
file_free(fsp);
DEBUG(0, ("Could not get share mode lock\n"));
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
- return NULL;
+ return NT_STATUS_SHARING_VIOLATION;
}
/* First pass - send break only on batch oplocks. */
@@ -1386,31 +1435,33 @@ files_struct *open_file_ntcreate(connection_struct *conn,
schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
file_free(fsp);
- return NULL;
+ return NT_STATUS_SHARING_VIOLATION;
}
- /* Use the client requested access mask here, not the one we open with. */
+ /* Use the client requested access mask here, not the one we
+ * open with. */
status = open_mode_check(conn, fname, lck,
access_mask, share_access,
create_options, &file_existed);
if (NT_STATUS_IS_OK(status)) {
- /* We might be going to allow this open. Check oplock status again. */
- /* Second pass - send break for both batch or exclusive oplocks. */
+ /* We might be going to allow this open. Check oplock
+ * status again. */
+ /* Second pass - send break for both batch or
+ * exclusive oplocks. */
if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
file_free(fsp);
- return NULL;
+ return NT_STATUS_SHARING_VIOLATION;
}
}
if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
/* DELETE_PENDING is not deferred for a second */
- set_saved_ntstatus(status);
TALLOC_FREE(lck);
file_free(fsp);
- return NULL;
+ return status;
}
if (!NT_STATUS_IS_OK(status)) {
@@ -1426,7 +1477,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
files_struct *fsp_dup;
- /* Use the client requested access mask here, not the one we open with. */
+ /* Use the client requested access mask here,
+ * not the one we open with. */
fsp_dup = fcb_or_dos_open(conn, fname, dev,
inode, access_mask,
share_access,
@@ -1439,7 +1491,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
*pinfo = FILE_WAS_OPENED;
}
conn->num_files_open++;
- return fsp_dup;
+ *result = fsp_dup;
+ return NT_STATUS_OK;
}
}
@@ -1455,15 +1508,17 @@ files_struct *open_file_ntcreate(connection_struct *conn,
if (flags & O_RDWR) {
can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
+ } else if (flags & O_WRONLY) {
+ can_access_mask = FILE_WRITE_DATA;
} else {
can_access_mask = FILE_READ_DATA;
}
- if (((flags & O_RDWR) && !CAN_WRITE(conn)) ||
- !can_access_file(conn,fname,psbuf,can_access_mask)) {
+ if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
+ !can_access_file(conn,fname,psbuf,can_access_mask)) {
can_access = False;
}
-
+
/*
* If we're returning a share violation, ensure we
* cope with the braindead 1 second delay.
@@ -1477,7 +1532,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
/* this is a hack to speed up torture tests
in 'make test' */
- timeout_usecs = lp_parm_int(conn->service,
+ timeout_usecs = lp_parm_int(SNUM(conn),
"smbd","sharedelay",
SHARING_VIOLATION_USEC_WAIT);
@@ -1508,17 +1563,17 @@ files_struct *open_file_ntcreate(connection_struct *conn,
}
TALLOC_FREE(lck);
- if (!can_access) {
- set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
- } else {
+ if (can_access) {
/*
* We have detected a sharing violation here
* so return the correct error code
*/
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
+ status = NT_STATUS_SHARING_VIOLATION;
+ } else {
+ status = NT_STATUS_ACCESS_DENIED;
}
file_free(fsp);
- return NULL;
+ return status;
}
/*
@@ -1533,8 +1588,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
*/
if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
- (def_acl = directory_has_default_acl(conn,
- parent_dirname(fname)))) {
+ (def_acl = directory_has_default_acl(conn, parent_dir))) {
unx_mode = 0777;
}
@@ -1548,15 +1602,16 @@ files_struct *open_file_ntcreate(connection_struct *conn,
* open_file strips any O_TRUNC flags itself.
*/
- fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
- access_mask, open_access_mask);
+ fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf,
+ flags|flags2, unx_mode, access_mask,
+ open_access_mask);
- if (!fsp_open) {
+ if (!NT_STATUS_IS_OK(fsp_open)) {
if (lck != NULL) {
TALLOC_FREE(lck);
}
file_free(fsp);
- return NULL;
+ return fsp_open;
}
if (!file_existed) {
@@ -1580,15 +1635,15 @@ files_struct *open_file_ntcreate(connection_struct *conn,
inode = fsp->inode;
lck = get_share_mode_lock(NULL, dev, inode,
- conn->connectpath,
- fname);
+ conn->connectpath,
+ fname);
if (lck == NULL) {
- DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
+ DEBUG(0, ("open_file_ntcreate: Could not get share "
+ "mode lock for %s\n", fname));
fd_close(conn, fsp);
file_free(fsp);
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
- return NULL;
+ return NT_STATUS_SHARING_VIOLATION;
}
status = open_mode_check(conn, fname, lck,
@@ -1615,7 +1670,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
defer_open(lck, request_time, timeval_zero(),
&state);
TALLOC_FREE(lck);
- return NULL;
+ return status;
}
/*
@@ -1631,9 +1686,18 @@ files_struct *open_file_ntcreate(connection_struct *conn,
these only read them. Nobody but Samba can ever set a deny
mode and we have already checked our more authoritative
locking database for permission to set this deny mode. If
- the kernel refuses the operations then the kernel is wrong */
+ the kernel refuses the operations then the kernel is wrong.
+ note that GPFS supports it as well - jmcd */
- kernel_flock(fsp, share_access);
+ ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access);
+ if(ret_flock == -1 ){
+
+ TALLOC_FREE(lck);
+ fd_close(conn, fsp);
+ file_free(fsp);
+
+ return NT_STATUS_SHARING_VIOLATION;
+ }
/*
* At this point onwards, we can guarentee that the share entry
@@ -1652,10 +1716,11 @@ files_struct *open_file_ntcreate(connection_struct *conn,
*/
if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) ||
(SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) {
+ status = map_nt_error_from_unix(errno);
TALLOC_FREE(lck);
fd_close(conn,fsp);
file_free(fsp);
- return NULL;
+ return status;
}
}
@@ -1677,11 +1742,6 @@ files_struct *open_file_ntcreate(connection_struct *conn,
}
} else {
info = 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 (pinfo) {
@@ -1703,34 +1763,33 @@ files_struct *open_file_ntcreate(connection_struct *conn,
set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type);
if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
- info == FILE_WAS_SUPERSEDED) {
+ info == FILE_WAS_SUPERSEDED) {
/* Handle strange delete on close create semantics. */
if (create_options & FILE_DELETE_ON_CLOSE) {
- NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes);
+ status = can_set_delete_on_close(fsp, True, new_dos_attributes);
- if (!NT_STATUS_IS_OK(result)) {
+ if (!NT_STATUS_IS_OK(status)) {
/* Remember to delete the mode we just added. */
del_share_mode(lck, fsp);
TALLOC_FREE(lck);
fd_close(conn,fsp);
file_free(fsp);
- set_saved_ntstatus(result);
- return NULL;
+ return status;
}
/* Note that here we set the *inital* delete on close flag,
- not the regular one. */
- set_delete_on_close_token(lck, &current_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
}
/* Files should be initially set as archive */
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
- file_set_dosmode(conn, fname,
+ if (!posix_open) {
+ file_set_dosmode(conn, fname,
new_dos_attributes | aARCH, NULL,
- True);
+ parent_dir);
+ }
}
}
@@ -1739,13 +1798,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
* selected.
*/
- if (!file_existed && !def_acl) {
+ if (!posix_open && !file_existed && !def_acl) {
int saved_errno = errno; /* We might get ENOSYS in the next
* call.. */
- if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1
- && errno == ENOSYS) {
+ if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 &&
+ errno == ENOSYS) {
errno = saved_errno; /* Ignore ENOSYS */
}
@@ -1766,7 +1825,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
} else {
DEBUG(5, ("open_file_ntcreate: reset "
"attributes of file %s to 0%o\n",
- fname, (unsigned int)new_unx_mode));
+ fname, (unsigned int)new_unx_mode));
ret = 0; /* Don't do the fchmod below. */
}
}
@@ -1775,7 +1834,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
(SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1))
DEBUG(5, ("open_file_ntcreate: failed to reset "
"attributes of file %s to 0%o\n",
- fname, (unsigned int)new_unx_mode));
+ fname, (unsigned int)new_unx_mode));
}
/* If this is a successful open, we must remove any deferred open
@@ -1785,31 +1844,33 @@ files_struct *open_file_ntcreate(connection_struct *conn,
conn->num_files_open++;
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
}
/****************************************************************************
Open a file for for write to ensure that we can fchmod it.
****************************************************************************/
-files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
- SMB_STRUCT_STAT *psbuf)
+NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf, files_struct **result)
{
files_struct *fsp = NULL;
- BOOL fsp_open;
+ NTSTATUS status;
if (!VALID_STAT(*psbuf)) {
- return NULL;
+ return NT_STATUS_INVALID_PARAMETER;
}
- fsp = file_new(conn);
- if(!fsp) {
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* note! we must use a non-zero desired access or we don't get
a real file descriptor. Oh what a twisted web we weave. */
- fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA);
+ status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0,
+ FILE_WRITE_DATA, FILE_WRITE_DATA);
/*
* This is not a user visible file open.
@@ -1817,98 +1878,198 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
* the conn->num_files_open.
*/
- if (!fsp_open) {
+ if (!NT_STATUS_IS_OK(status)) {
file_free(fsp);
- return NULL;
+ return status;
}
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
}
/****************************************************************************
Close the fchmod file fd - ensure no locks are lost.
****************************************************************************/
-int close_file_fchmod(files_struct *fsp)
+NTSTATUS close_file_fchmod(files_struct *fsp)
{
- int ret = fd_close(fsp->conn, fsp);
+ NTSTATUS status = fd_close(fsp->conn, fsp);
file_free(fsp);
- return ret;
+ return status;
+}
+
+static NTSTATUS mkdir_internal(connection_struct *conn,
+ const char *name,
+ uint32 file_attributes,
+ SMB_STRUCT_STAT *psbuf)
+{
+ int ret= -1;
+ mode_t mode;
+ char *parent_dir;
+ const char *dirname;
+ NTSTATUS status;
+
+ if(!CAN_WRITE(conn)) {
+ DEBUG(5,("mkdir_internal: failing create on read-only share "
+ "%s\n", lp_servicename(SNUM(conn))));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ status = check_name(conn, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir,
+ &dirname)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
+ } else {
+ mode = unix_mode(conn, aDIR, name, parent_dir);
+ }
+
+ if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
+ return map_nt_error_from_unix(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, name, psbuf) == -1) {
+ DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
+ name, strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (!S_ISDIR(psbuf->st_mode)) {
+ DEBUG(0, ("Directory just '%s' created is not a directory\n",
+ name));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (lp_inherit_perms(SNUM(conn))) {
+ inherit_access_acl(conn, parent_dir, name, mode);
+ }
+
+ if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
+ /*
+ * Check if high bits should have been set,
+ * then (if bits are missing): add them.
+ * Consider bits automagically set by UNIX, i.e. SGID bit from parent
+ * dir.
+ */
+ if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
+ SMB_VFS_CHMOD(conn, name,
+ psbuf->st_mode | (mode & ~psbuf->st_mode));
+ }
+ }
+
+ /* Change the owner if required. */
+ if (lp_inherit_owner(SNUM(conn))) {
+ change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
+ }
+
+ notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
+ name);
+
+ return NT_STATUS_OK;
}
/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
-files_struct *open_directory(connection_struct *conn,
- const char *fname,
- SMB_STRUCT_STAT *psbuf,
- uint32 access_mask,
- uint32 share_access,
- uint32 create_disposition,
- uint32 create_options,
- int *pinfo)
+NTSTATUS open_directory(connection_struct *conn,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 access_mask,
+ uint32 share_access,
+ uint32 create_disposition,
+ uint32 create_options,
+ uint32 file_attributes,
+ int *pinfo,
+ files_struct **result)
{
files_struct *fsp = NULL;
BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
- BOOL create_dir = False;
struct share_mode_lock *lck = NULL;
NTSTATUS status;
int info = 0;
DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
"share_access = 0x%x create_options = 0x%x, "
- "create_disposition = 0x%x\n",
+ "create_disposition = 0x%x, file_attributes = 0x%x\n",
fname,
(unsigned int)access_mask,
(unsigned int)share_access,
(unsigned int)create_options,
- (unsigned int)create_disposition));
+ (unsigned int)create_disposition,
+ (unsigned int)file_attributes));
if (is_ntfs_stream_name(fname)) {
DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
- set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY);
- return NULL;
+ return NT_STATUS_NOT_A_DIRECTORY;
}
switch( create_disposition ) {
case FILE_OPEN:
- /* If directory exists open. If directory doesn't
- * exist error. */
- if (!dir_existed) {
- DEBUG(5,("open_directory: FILE_OPEN requested "
- "for directory %s and it doesn't "
- "exist.\n", fname ));
- set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return NULL;
- }
+
info = FILE_WAS_OPENED;
+
+ /*
+ * We want to follow symlinks here.
+ */
+
+ if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
break;
case FILE_CREATE:
+
/* If directory exists error. If directory doesn't
* exist create. */
- if (dir_existed) {
- DEBUG(5,("open_directory: FILE_CREATE "
- "requested for directory %s and it "
- "already exists.\n", fname ));
- set_saved_error_triple(ERRDOS, ERRfilexists,
- NT_STATUS_OBJECT_NAME_COLLISION);
- return NULL;
+
+ status = mkdir_internal(conn,
+ fname,
+ file_attributes,
+ psbuf);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("open_directory: unable to create "
+ "%s. Error was %s\n", fname,
+ nt_errstr(status)));
+ return status;
}
- create_dir = True;
+
info = FILE_WAS_CREATED;
break;
case FILE_OPEN_IF:
- /* If directory exists open. If directory doesn't
- * exist create. */
- if (!dir_existed) {
- create_dir = True;
+ /*
+ * If directory exists open. If directory doesn't
+ * exist create.
+ */
+
+ status = mkdir_internal(conn,
+ fname,
+ file_attributes,
+ psbuf);
+
+ if (NT_STATUS_IS_OK(status)) {
info = FILE_WAS_CREATED;
- } else {
+ }
+
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
info = FILE_WAS_OPENED;
+ status = NT_STATUS_OK;
}
+
break;
case FILE_SUPERSEDE:
@@ -1918,45 +2079,18 @@ files_struct *open_directory(connection_struct *conn,
DEBUG(5,("open_directory: invalid create_disposition "
"0x%x for directory %s\n",
(unsigned int)create_disposition, fname));
- set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
- return NULL;
+ return NT_STATUS_INVALID_PARAMETER;
}
- if (create_dir) {
- /*
- * Try and create the directory.
- */
-
- /* We know bad_path is false as it's caught earlier. */
-
- status = mkdir_internal(conn, fname, False);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("open_directory: unable to create %s. "
- "Error was %s\n", fname, strerror(errno) ));
- /* Ensure we return the correct NT status to the
- * client. */
- set_saved_error_triple(0, 0, status);
- return NULL;
- }
-
- /* 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) {
- return NULL;
- }
-
- if(!S_ISDIR(psbuf->st_mode)) {
- DEBUG(0,("open_directory: %s is not a directory !\n",
- fname ));
- return NULL;
- }
+ if(!S_ISDIR(psbuf->st_mode)) {
+ DEBUG(5,("open_directory: %s is not a directory !\n",
+ fname ));
+ return NT_STATUS_NOT_A_DIRECTORY;
}
- fsp = file_new(conn);
- if(!fsp) {
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
@@ -1968,7 +2102,7 @@ files_struct *open_directory(connection_struct *conn,
fsp->dev = psbuf->st_dev;
fsp->vuid = current_user.vuid;
fsp->file_pid = global_smbpid;
- fsp->can_lock = True;
+ fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
@@ -1982,17 +2116,18 @@ files_struct *open_directory(connection_struct *conn,
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True;
fsp->is_stat = False;
+ fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
+
string_set(&fsp->fsp_name,fname);
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode,
- conn->connectpath,
- fname);
+ conn->connectpath,
+ fname);
if (lck == NULL) {
DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
file_free(fsp);
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
- return NULL;
+ return NT_STATUS_SHARING_VIOLATION;
}
status = open_mode_check(conn, fname, lck,
@@ -2000,10 +2135,9 @@ files_struct *open_directory(connection_struct *conn,
create_options, &dir_existed);
if (!NT_STATUS_IS_OK(status)) {
- set_saved_ntstatus(status);
TALLOC_FREE(lck);
file_free(fsp);
- return NULL;
+ return status;
}
set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK);
@@ -2012,53 +2146,78 @@ files_struct *open_directory(connection_struct *conn,
always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
if (create_options & FILE_DELETE_ON_CLOSE) {
status = can_set_delete_on_close(fsp, True, 0);
- if (!NT_STATUS_IS_OK(status)) {
- set_saved_ntstatus(status);
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
TALLOC_FREE(lck);
file_free(fsp);
- return NULL;
+ return status;
}
- set_delete_on_close_token(lck, &current_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ if (NT_STATUS_IS_OK(status)) {
+ /* Note that here we set the *inital* delete on close flag,
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
+ }
}
TALLOC_FREE(lck);
- /* Change the owner if required. */
- if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
- change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf);
- }
-
if (pinfo) {
*pinfo = info;
}
conn->num_files_open++;
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS create_directory(connection_struct *conn, const char *directory)
+{
+ NTSTATUS status;
+ SMB_STRUCT_STAT sbuf;
+ files_struct *fsp;
+
+ SET_STAT_INVALID(sbuf);
+
+ status = open_directory(conn, directory, &sbuf,
+ FILE_READ_ATTRIBUTES, /* Just a stat open */
+ FILE_SHARE_NONE, /* Ignored for stat opens */
+ FILE_CREATE,
+ 0,
+ FILE_ATTRIBUTE_DIRECTORY,
+ NULL,
+ &fsp);
+
+ if (NT_STATUS_IS_OK(status)) {
+ close_file(fsp, NORMAL_CLOSE);
+ }
+
+ return status;
}
/****************************************************************************
Open a pseudo-file (no locking checks - a 'stat' open).
****************************************************************************/
-files_struct *open_file_stat(connection_struct *conn, char *fname,
- SMB_STRUCT_STAT *psbuf)
+NTSTATUS open_file_stat(connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf, files_struct **result)
{
files_struct *fsp = NULL;
+ NTSTATUS status;
- if (!VALID_STAT(*psbuf))
- return NULL;
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
/* Can't 'stat' open directories. */
- if(S_ISDIR(psbuf->st_mode))
- return NULL;
+ if(S_ISDIR(psbuf->st_mode)) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
- fsp = file_new(conn);
- if(!fsp)
- return NULL;
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
DEBUG(5,("open_file_stat: 'opening' file %s\n", fname));
@@ -2084,7 +2243,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
conn->num_files_open++;
- return fsp;
+ *result = fsp;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -2092,7 +2252,8 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
smbd process.
****************************************************************************/
-void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len)
+void msg_file_was_renamed(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
files_struct *fsp;
char *frm = (char *)buf;
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index e4f5c434b09..423d6b3a999 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -342,12 +342,19 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un
return fsp;
}
-static void oplock_timeout_handler(struct timed_event *te,
+static void oplock_timeout_handler(struct event_context *ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data)
{
- files_struct *fsp = private_data;
+ files_struct *fsp = (files_struct *)private_data;
+ /* Ensure we always remove this event. */
+ if (fsp->oplock_timeout != NULL) {
+ /* Remove the timed event handler. */
+ TALLOC_FREE(fsp->oplock_timeout);
+ fsp->oplock_timeout = NULL;
+ }
DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name));
global_client_failed_oplock_break = True;
remove_oplock(fsp);
@@ -366,7 +373,7 @@ static void add_oplock_timeout_handler(files_struct *fsp)
}
fsp->oplock_timeout =
- add_timed_event(NULL,
+ event_add_timed(smbd_event_context(), NULL,
timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
"oplock_timeout_handler",
oplock_timeout_handler, fsp);
@@ -385,7 +392,8 @@ static void add_oplock_timeout_handler(files_struct *fsp)
*******************************************************************/
static void process_oplock_async_level2_break_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
files_struct *fsp;
@@ -403,7 +411,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)buf);
DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n",
(int)procid_to_pid(&src), (unsigned int)msg.dev,
@@ -454,7 +462,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce
show_msg(break_msg);
if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server("oplock_break: send_smb failed.");
+ exit_server_cleanly("oplock_break: send_smb failed.");
}
/* Restore the sign state to what it was. */
@@ -471,7 +479,8 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce
*******************************************************************/
static void process_oplock_break_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
files_struct *fsp;
@@ -490,7 +499,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)buf);
DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n",
(int)procid_to_pid(&src), (unsigned int)msg.dev,
@@ -504,13 +513,10 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
* get to process this message, we have closed the file. Reply
* with 'ok, oplock broken' */
DEBUG(3, ("Did not find fsp\n"));
- become_root();
/* We just send the same message back. */
message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
-
- unbecome_root();
return;
}
@@ -529,13 +535,9 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n",
(unsigned int)fsp->dev, (double)fsp->inode,
fsp->fsp_name));
- become_root();
-
/* We just send the same message back. */
message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
-
- unbecome_root();
return;
}
@@ -563,7 +565,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
show_msg(break_msg);
if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server("oplock_break: send_smb failed.");
+ exit_server_cleanly("oplock_break: send_smb failed.");
}
/* Restore the sign state to what it was. */
@@ -586,7 +588,8 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
*******************************************************************/
static void process_kernel_oplock_break(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
SMB_DEV_T dev;
SMB_INO_T inode;
@@ -639,7 +642,7 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src,
show_msg(break_msg);
if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server("oplock_break: send_smb failed.");
+ exit_server_cleanly("oplock_break: send_smb failed.");
}
/* Restore the sign state to what it was. */
@@ -656,7 +659,6 @@ void reply_to_oplock_break_requests(files_struct *fsp)
{
int i;
- become_root();
for (i=0; i<fsp->num_pending_break_messages; i++) {
struct share_mode_entry *e = &fsp->pending_break_messages[i];
char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
@@ -666,7 +668,6 @@ void reply_to_oplock_break_requests(files_struct *fsp)
message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE,
msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
}
- unbecome_root();
SAFE_FREE(fsp->pending_break_messages);
fsp->num_pending_break_messages = 0;
@@ -679,7 +680,8 @@ void reply_to_oplock_break_requests(files_struct *fsp)
}
static void process_oplock_break_response(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
@@ -694,7 +696,7 @@ static void process_oplock_break_response(int msg_type, struct process_id src,
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)buf);
DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n",
(int)procid_to_pid(&src), (unsigned int)msg.dev,
@@ -706,7 +708,8 @@ static void process_oplock_break_response(int msg_type, struct process_id src,
}
static void process_open_retry_message(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
@@ -721,7 +724,7 @@ static void process_open_retry_message(int msg_type, struct process_id src,
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, buf);
+ message_to_share_mode_entry(&msg, (char *)buf);
DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n",
(int)procid_to_pid(&src), (unsigned int)msg.dev,
@@ -801,10 +804,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
share_mode_entry_to_message(msg, share_entry);
- become_root();
message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK,
msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
- unbecome_root();
}
/* We let the message receivers handle removing the oplock state
@@ -831,6 +832,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
SINO_T_VAL(msg,36,e->inode);
SIVAL(msg,44,e->share_file_id);
SIVAL(msg,48,e->uid);
+ SSVAL(msg,52,e->flags);
}
/****************************************************************************
@@ -851,6 +853,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
e->inode = INO_T_VAL(msg,36);
e->share_file_id = (unsigned long)IVAL(msg,44);
e->uid = (uint32)IVAL(msg,48);
+ e->flags = (uint16)SVAL(msg,52);
}
/****************************************************************************
@@ -859,18 +862,23 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
BOOL init_oplocks(void)
{
- DEBUG(3,("open_oplock_ipc: initializing messages.\n"));
+ DEBUG(3,("init_oplocks: initializing messages.\n"));
message_register(MSG_SMB_BREAK_REQUEST,
- process_oplock_break_message);
+ process_oplock_break_message,
+ NULL);
message_register(MSG_SMB_ASYNC_LEVEL2_BREAK,
- process_oplock_async_level2_break_message);
+ process_oplock_async_level2_break_message,
+ NULL);
message_register(MSG_SMB_BREAK_RESPONSE,
- process_oplock_break_response);
+ process_oplock_break_response,
+ NULL);
message_register(MSG_SMB_KERNEL_BREAK,
- process_kernel_oplock_break);
+ process_kernel_oplock_break,
+ NULL);
message_register(MSG_SMB_OPEN_RETRY,
- process_open_retry_message);
+ process_open_retry_message,
+ NULL);
if (lp_kernel_oplocks()) {
#if HAVE_KERNEL_OPLOCKS_IRIX
diff --git a/source/smbd/oplock_irix.c b/source/smbd/oplock_irix.c
index 248d9020283..c1159cd73b4 100644
--- a/source/smbd/oplock_irix.c
+++ b/source/smbd/oplock_irix.c
@@ -38,16 +38,19 @@ static BOOL irix_oplocks_available(void)
set_effective_capability(KERNEL_OPLOCK_CAPABILITY);
- slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid());
+ slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(),
+ (int)sys_getpid());
if(pipe(pfd) != 0) {
- DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n",
+ DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error "
+ "was %s\n",
strerror(errno) ));
return False;
}
if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) {
- DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n",
+ DEBUG(0,("check_kernel_oplocks: Unable to open temp test file "
+ "%s. Error was %s\n",
tmpname, strerror(errno) ));
unlink( tmpname );
close(pfd[0]);
@@ -58,8 +61,9 @@ static BOOL irix_oplocks_available(void)
unlink(tmpname);
if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) {
- DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \
-Disabling kernel oplock support.\n" ));
+ DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not "
+ "available on this machine. Disabling kernel oplock "
+ "support.\n" ));
close(pfd[0]);
close(pfd[1]);
close(fd);
@@ -67,8 +71,9 @@ Disabling kernel oplock support.\n" ));
}
if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
- DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
-Disabling kernel oplock support.\n", strerror(errno) ));
+ DEBUG(0,("check_kernel_oplocks: Error when removing kernel "
+ "oplock. Error was %s. Disabling kernel oplock "
+ "support.\n", strerror(errno) ));
close(pfd[0]);
close(pfd[1]);
close(fd);
@@ -145,7 +150,8 @@ static files_struct *irix_oplock_receive_message(fd_set *fds)
DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
"received for dev = %x, inode = %.0f\n, file_id = %ul",
- (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id ));
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id ));
return fsp;
}
@@ -158,20 +164,28 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) {
if(errno != EAGAIN) {
- DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \
-inode = %.0f, file_id = %ul. Error was %s\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id,
+ DEBUG(0,("irix_set_kernel_oplock: Unable to get "
+ "kernel oplock on file %s, dev = %x, inode "
+ "= %.0f, file_id = %ul. Error was %s\n",
+ fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, fsp->fh->file_id,
strerror(errno) ));
} else {
- DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
-inode = %.0f, file_id = %ul. Another process had the file open.\n",
- fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id ));
+ DEBUG(5,("irix_set_kernel_oplock: Refused oplock on "
+ "file %s, fd = %d, dev = %x, inode = %.0f, "
+ "file_id = %ul. Another process had the file "
+ "open.\n",
+ fsp->fsp_name, fsp->fh->fd,
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id ));
}
return False;
}
- DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id));
+ DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev "
+ "= %x, inode = %.0f, file_id = %ul\n",
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id));
return True;
}
@@ -188,8 +202,9 @@ static void irix_release_kernel_oplock(files_struct *fsp)
* oplock state of this file.
*/
int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
- dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \
-oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
+ dbgtext("irix_release_kernel_oplock: file %s, dev = %x, "
+ "inode = %.0f file_id = %ul, has kernel oplock state "
+ "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->fh->file_id, state );
}
@@ -198,10 +213,13 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
*/
if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) {
if( DEBUGLVL( 0 )) {
- dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " );
- dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n",
+ dbgtext("irix_release_kernel_oplock: Error when "
+ "removing kernel oplock on file " );
+ dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. "
+ "Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->fh->file_id, strerror(errno) );
+ (double)fsp->inode, fsp->fh->file_id,
+ strerror(errno) );
}
}
}
@@ -249,8 +267,8 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void)
return NULL;
if(pipe(pfd) != 0) {
- DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n",
- strerror(errno) ));
+ DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. "
+ "Error was %s\n", strerror(errno) ));
return False;
}
@@ -266,5 +284,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void)
return &koplocks;
}
#else
+ void oplock_irix_dummy(void);
void oplock_irix_dummy(void) {}
#endif /* HAVE_KERNEL_OPLOCKS_IRIX */
diff --git a/source/smbd/oplock_linux.c b/source/smbd/oplock_linux.c
index f186c13ebdd..14db98cde6c 100644
--- a/source/smbd/oplock_linux.c
+++ b/source/smbd/oplock_linux.c
@@ -89,7 +89,8 @@ static void set_capability(unsigned capability)
header.pid = 0;
if (capget(&header, &data) == -1) {
- DEBUG(3,("Unable to get kernel capabilities (%s)\n", strerror(errno)));
+ DEBUG(3,("Unable to get kernel capabilities (%s)\n",
+ strerror(errno)));
return;
}
@@ -101,20 +102,29 @@ static void set_capability(unsigned capability)
}
}
+/*
+ Call to set the kernel lease signal handler
+*/
+int linux_set_lease_sighandler(int fd)
+{
+ if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
+ DEBUG(3,("Failed to set signal handler for kernel lease\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
/****************************************************************************
Call SETLEASE. If we get EACCES then we try setting up the right capability and
- try again
+ try again.
+ Use the SMB_VFS_LINUX_SETLEASE instead of this call directly.
****************************************************************************/
-static int linux_setlease(int fd, int leasetype)
+int linux_setlease(int fd, int leasetype)
{
int ret;
- if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
- DEBUG(3,("Failed to set signal handler for kernel lease\n"));
- return -1;
- }
-
ret = fcntl(fd, F_SETLEASE, leasetype);
if (ret == -1 && errno == EACCES) {
set_capability(CAP_LEASE);
@@ -155,16 +165,19 @@ static files_struct *linux_oplock_receive_message(fd_set *fds)
static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
- if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) {
- DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
-inode = %.0f. (%s)\n",
+ if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) {
+ DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, "
+ "fd = %d, dev = %x, inode = %.0f. (%s)\n",
fsp->fsp_name, fsp->fh->fd,
- (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno)));
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ strerror(errno)));
return False;
}
- DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id));
+ DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, "
+ "dev = %x, inode = %.0f, file_id = %lu\n",
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id));
return True;
}
@@ -181,20 +194,23 @@ static void linux_release_kernel_oplock(files_struct *fsp)
* oplock state of this file.
*/
int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
- dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \
-oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
+ dbgtext("linux_release_kernel_oplock: file %s, dev = %x, "
+ "inode = %.0f file_id = %lu has kernel oplock state "
+ "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->fh->file_id, state );
}
/*
* Remove the kernel oplock on this file.
*/
- if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) {
+ if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_UNLCK) == -1) {
if (DEBUGLVL(0)) {
- dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " );
- dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n",
- fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->fh->file_id, strerror(errno) );
+ dbgtext("linux_release_kernel_oplock: Error when "
+ "removing kernel oplock on file " );
+ dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. "
+ "Error was %s\n", fsp->fsp_name,
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id, strerror(errno) );
}
}
}
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 814065dd34a..bf4e9258ff2 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -23,15 +23,14 @@
/* users from session setup */
static char *session_userlist = NULL;
static int len_session_userlist = 0;
+/* workgroup from session setup. */
+static char *session_workgroup = NULL;
/* this holds info on user ids that are already validated for this VC */
static user_struct *validated_users;
static int next_vuid = VUID_OFFSET;
static int num_validated_vuids;
-extern userdom_struct current_user_info;
-
-
/****************************************************************************
Check if a uid has been validated, and return an pointer to the user_struct
if it has. NULL if not. vuid is biased by an offset. This allows us to
@@ -112,6 +111,7 @@ void invalidate_vuid(uint16 vuid)
SAFE_FREE(vuser->groups);
TALLOC_FREE(vuser->nt_user_token);
+
SAFE_FREE(vuser);
num_validated_vuids--;
}
@@ -406,6 +406,29 @@ void add_session_user(const char *user)
}
/****************************************************************************
+ In security=share mode we need to store the client workgroup, as that's
+ what Vista uses for the NTLMv2 calculation.
+****************************************************************************/
+
+void add_session_workgroup(const char *workgroup)
+{
+ if (session_workgroup) {
+ SAFE_FREE(session_workgroup);
+ }
+ session_workgroup = smb_xstrdup(workgroup);
+}
+
+/****************************************************************************
+ In security=share mode we need to return the client workgroup, as that's
+ what Vista uses for the NTLMv2 calculation.
+****************************************************************************/
+
+const char *get_session_workgroup(void)
+{
+ return session_workgroup;
+}
+
+/****************************************************************************
Check if a user is in a netgroup user list. If at first we don't succeed,
try lower case.
****************************************************************************/
@@ -549,9 +572,11 @@ static BOOL user_ok(const char *user, int snum)
str_list_copy(&invalid, lp_invalid_users(snum));
if (invalid &&
str_list_substitute(invalid, "%S", lp_servicename(snum))) {
- if ( invalid &&
- str_list_sub_basic(invalid,
- current_user_info.smb_name) ) {
+
+ /* This is used in sec=share only, so no current user
+ * around to pass to str_list_sub_basic() */
+
+ if ( invalid && str_list_sub_basic(invalid, "", "") ) {
ret = !user_in_list(user,
(const char **)invalid);
}
@@ -564,9 +589,11 @@ static BOOL user_ok(const char *user, int snum)
str_list_copy(&valid, lp_valid_users(snum));
if ( valid &&
str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
- if ( valid &&
- str_list_sub_basic(valid,
- current_user_info.smb_name) ) {
+
+ /* This is used in sec=share only, so no current user
+ * around to pass to str_list_sub_basic() */
+
+ if ( valid && str_list_sub_basic(valid, "", "") ) {
ret = user_in_list(user, (const char **)valid);
}
}
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 2d90383706b..52660da2ffe 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -31,6 +31,21 @@
#define PIPE "\\PIPE\\"
#define PIPELEN strlen(PIPE)
+#define MAX_PIPE_NAME_LEN 24
+
+/* PIPE/<name>/<pid>/<pnum> */
+#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d"
+
+struct pipe_dbrec {
+ struct process_id pid;
+ int pnum;
+ uid_t uid;
+
+ char name[MAX_PIPE_NAME_LEN];
+ fstring user;
+};
+
+
extern struct pipe_id_info pipe_names[];
/****************************************************************************
@@ -284,6 +299,8 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
if (!close_rpc_pipe_hnd(p)) {
return ERROR_DOS(ERRDOS,ERRbadfid);
}
+
+ /* TODO: REMOVE PIPE FROM DB */
return(outsize);
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 486149f4348..50038dd464c 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -169,7 +169,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B
*store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH);
- pai_buf = SMB_MALLOC(*store_size);
+ pai_buf = (char *)SMB_MALLOC(*store_size);
if (!pai_buf) {
return NULL;
}
@@ -441,7 +441,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp)
if (!lp_map_acl_inherit(SNUM(fsp->conn)))
return NULL;
- if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)
+ if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
return NULL;
do {
@@ -462,7 +462,7 @@ static struct pai_val *load_inherited_info(files_struct *fsp)
if (pai_buf_size > 1024*1024) {
return NULL; /* Limit malloc to 1mb. */
}
- if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)
+ if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
return NULL;
}
} while (ret == -1);
@@ -575,6 +575,9 @@ static void print_canon_ace(canon_ace *pace, int num)
case SMB_ACL_OTHER:
dbgtext( "SMB_ACL_OTHER ");
break;
+ default:
+ dbgtext( "MASK " );
+ break;
}
if (pace->inherited)
dbgtext( "(inherited) ");
@@ -655,6 +658,7 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC
}
return 0;
}
+
/****************************************************************************
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
****************************************************************************/
@@ -666,6 +670,27 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI
}
/****************************************************************************
+ Is the identity in two ACEs equal ? Check both SID and uid/gid.
+****************************************************************************/
+
+static BOOL identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
+{
+ if (sid_equal(&ace1->trustee, &ace2->trustee)) {
+ return True;
+ }
+ if (ace1->owner_type == ace2->owner_type) {
+ if (ace1->owner_type == UID_ACE &&
+ ace1->unix_ug.uid == ace2->unix_ug.uid) {
+ return True;
+ } else if (ace1->owner_type == GID_ACE &&
+ ace1->unix_ug.gid == ace2->unix_ug.gid) {
+ return True;
+ }
+ }
+ return False;
+}
+
+/****************************************************************************
Merge aces with a common sid - if both are allow or deny, OR the permissions together and
delete the second one. If the first is deny, mask the permissions off and delete the allow
if the permissions become zero, delete the deny if the permissions are non zero.
@@ -692,7 +717,7 @@ static void merge_aces( canon_ace **pp_list_head )
curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
- if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
(curr_ace->attr == curr_ace_outer->attr)) {
if( DEBUGLVL( 10 )) {
@@ -732,7 +757,7 @@ static void merge_aces( canon_ace **pp_list_head )
* we've put on the ACL, we know the deny must be the first one.
*/
- if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
(curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
if( DEBUGLVL( 10 )) {
@@ -857,36 +882,36 @@ static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_
#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
-static mode_t map_nt_perms( SEC_ACCESS sec_access, int type)
+static mode_t map_nt_perms( uint32 *mask, int type)
{
mode_t mode = 0;
switch(type) {
case S_IRUSR:
- if(sec_access.mask & GENERIC_ALL_ACCESS)
+ if((*mask) & GENERIC_ALL_ACCESS)
mode = S_IRUSR|S_IWUSR|S_IXUSR;
else {
- mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
- mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
- mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
+ mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
+ mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
+ mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
}
break;
case S_IRGRP:
- if(sec_access.mask & GENERIC_ALL_ACCESS)
+ if((*mask) & GENERIC_ALL_ACCESS)
mode = S_IRGRP|S_IWGRP|S_IXGRP;
else {
- mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
- mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
- mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
+ mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
+ mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
+ mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
}
break;
case S_IROTH:
- if(sec_access.mask & GENERIC_ALL_ACCESS)
+ if((*mask) & GENERIC_ALL_ACCESS)
mode = S_IROTH|S_IWOTH|S_IXOTH;
else {
- mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
- mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
- mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
+ mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
+ mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
+ mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
}
break;
}
@@ -898,7 +923,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type)
Unpack a SEC_DESC into a UNIX owner and group.
****************************************************************************/
-static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
+BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
{
DOM_SID owner_sid;
DOM_SID grp_sid;
@@ -947,7 +972,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid
*/
if (security_info_sent & GROUP_SECURITY_INFORMATION) {
- sid_copy(&grp_sid, psd->grp_sid);
+ sid_copy(&grp_sid, psd->group_sid);
if (!sid_to_gid( &grp_sid, pgrp)) {
if (lp_force_unknown_acl_user(snum)) {
/* this allows take group ownership to work
@@ -1238,7 +1263,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);
canon_ace *file_ace = NULL;
canon_ace *dir_ace = NULL;
- canon_ace *tmp_ace = NULL;
canon_ace *current_ace = NULL;
BOOL got_dir_allow = False;
BOOL got_file_allow = False;
@@ -1252,7 +1276,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
*/
for(i = 0; i < dacl->num_aces; i++) {
- SEC_ACE *psa = &dacl->ace[i];
+ SEC_ACE *psa = &dacl->aces[i];
if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
@@ -1271,12 +1295,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
* Convert GENERIC bits to specific bits.
*/
- se_map_generic(&psa->info.mask, &file_generic_mapping);
+ se_map_generic(&psa->access_mask, &file_generic_mapping);
- psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
+ psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
- if(psa->info.mask != UNIX_ACCESS_NONE)
- psa->info.mask &= ~UNIX_ACCESS_NONE;
+ if(psa->access_mask != UNIX_ACCESS_NONE)
+ psa->access_mask &= ~UNIX_ACCESS_NONE;
}
}
@@ -1289,12 +1313,12 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
*/
for(i = 0; i < dacl->num_aces; i++) {
- SEC_ACE *psa1 = &dacl->ace[i];
+ SEC_ACE *psa1 = &dacl->aces[i];
for (j = i + 1; j < dacl->num_aces; j++) {
- SEC_ACE *psa2 = &dacl->ace[j];
+ SEC_ACE *psa2 = &dacl->aces[j];
- if (psa1->info.mask != psa2->info.mask)
+ if (psa1->access_mask != psa2->access_mask)
continue;
if (!sid_equal(&psa1->trustee, &psa2->trustee))
@@ -1320,7 +1344,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
}
for(i = 0; i < dacl->num_aces; i++) {
- SEC_ACE *psa = &dacl->ace[i];
+ SEC_ACE *psa = &dacl->aces[i];
/*
* Ignore non-mappable SIDs (NT Authority, BUILTIN etc).
@@ -1406,7 +1430,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
* S_I(R|W|X)USR bits.
*/
- current_ace->perms |= map_nt_perms( psa->info, S_IRUSR);
+ current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR);
current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False);
@@ -1426,7 +1450,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
- DLIST_ADD_END(dir_ace, current_ace, tmp_ace);
+ DLIST_ADD_END(dir_ace, current_ace, canon_ace *);
/*
* Note if this was an allow ace. We can't process
@@ -1484,7 +1508,7 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
*/
if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
- DLIST_ADD_END(file_ace, current_ace, tmp_ace);
+ DLIST_ADD_END(file_ace, current_ace, canon_ace *);
/*
* Note if this was an allow ace. We can't process
@@ -1731,7 +1755,6 @@ static void process_deny_list( canon_ace **pp_ace_list )
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
mode_t new_perms = (mode_t)0;
canon_ace *allow_ace_p;
- canon_ace *tmp_ace;
curr_ace_next = curr_ace->next; /* So we can't lose the link. */
@@ -1750,7 +1773,7 @@ static void process_deny_list( canon_ace **pp_ace_list )
curr_ace->attr = ALLOW_ACE;
curr_ace->perms = (mode_t)0;
- DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
+ DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
continue;
}
@@ -1775,13 +1798,12 @@ static void process_deny_list( canon_ace **pp_ace_list )
curr_ace->attr = ALLOW_ACE;
curr_ace->perms = (new_perms & ~curr_ace->perms);
- DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
+ DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
}
/* Pass 3 above - deal with deny group entries. */
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
- canon_ace *tmp_ace;
canon_ace *allow_ace_p;
canon_ace *allow_everyone_p = NULL;
@@ -1823,8 +1845,7 @@ static void process_deny_list( canon_ace **pp_ace_list )
curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
else
curr_ace->perms = (mode_t)0;
- DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
-
+ DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
}
/* Doing this fourth pass allows Windows semantics to be layered
@@ -1879,7 +1900,10 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
mode_t or_bits = (mode_t)0;
- mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR;
+ mode_t mode = interitable_mode
+ ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name,
+ NULL )
+ : S_IRUSR;
if (fsp->is_directory)
mode |= (S_IWUSR|S_IXUSR);
@@ -2064,7 +2088,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
}
if (other_ace) {
- DLIST_DEMOTE(list_head, other_ace, ace);
+ DLIST_DEMOTE(list_head, other_ace, canon_ace *);
}
/* We have probably changed the head of the list. */
@@ -2436,17 +2460,6 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau
}
/*
- * Check if the ACL is valid.
- */
-
- if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) {
- DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n",
- the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
- strerror(errno) ));
- goto fail;
- }
-
- /*
* Finally apply it to the file or directory.
*/
@@ -2653,7 +2666,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
/* We know the lower number ACE's are file entries. */
if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
(nt_ace_list[i].size == nt_ace_list[j].size) &&
- (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) &&
+ (nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) &&
sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
(i_inh == j_inh) &&
(i_flags_ni == 0) &&
@@ -2666,7 +2679,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
* the non-inherited ACE onto the inherited ACE.
*/
- if (nt_ace_list[i].info.mask == 0) {
+ if (nt_ace_list[i].access_mask == 0) {
nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
(i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
if (num_aces - i - 1 > 0)
@@ -2966,7 +2979,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
}
if (psd->dacl) {
- dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces);
+ dacl_sort_into_canonical_order(psd->dacl->aces, (unsigned int)psd->dacl->num_aces);
}
*ppdesc = psd;
@@ -2997,7 +3010,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
then allow chown to the currently authenticated user.
****************************************************************************/
-static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
+int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
{
int ret;
files_struct *fsp;
@@ -3043,8 +3056,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_
return -1;
}
- fsp = open_file_fchmod(conn,fname,&st);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) {
return -1;
}
@@ -3114,7 +3126,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
* Unpack the user/group/world id's.
*/
- if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) {
+ if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
return False;
}
@@ -3470,19 +3482,17 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
}
/****************************************************************************
- If "inherit permissions" is set and the parent directory has no default
- ACL but it does have an Access ACL, inherit this Access ACL to file name.
+ If the parent directory has no default ACL but it does have an Access ACL,
+ inherit this Access ACL to file name.
****************************************************************************/
-int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode)
+int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir,
+ const char *name, mode_t mode)
{
- pstring dirname;
- pstrcpy(dirname, parent_dirname(name));
-
- if (!lp_inherit_perms(SNUM(conn)) || directory_has_default_acl(conn, dirname))
+ if (directory_has_default_acl(conn, inherit_from_dir))
return 0;
- return copy_access_acl(conn, dirname, name, mode);
+ return copy_access_acl(conn, inherit_from_dir, name, mode);
}
/****************************************************************************
@@ -4233,6 +4243,11 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
if (sbuf.st_mode & S_ISVTX) {
SMB_STRUCT_STAT sbuf_file;
if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
+ if (errno == ENOENT) {
+ /* If the file doesn't already exist then
+ * yes we'll be able to delete it. */
+ return True;
+ }
return False;
}
/*
@@ -4358,12 +4373,19 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
pstring filename;
ZERO_STRUCT( conn );
- conn.service = -1;
if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
return NULL;
}
+
+ if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) {
+ DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
+ TALLOC_FREE(conn.mem_ctx);
+ return NULL;
+ }
+
+ conn.params->service = -1;
pstrcpy( path, "/" );
set_conn_connectpath(&conn, path);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index b3ce49360d8..14941e64990 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -21,7 +21,7 @@
#include "includes.h"
-extern uint16 global_smbpid;
+uint16 global_smbpid;
extern int keepalive;
extern struct auth_context *negprot_global_auth_context;
extern int smb_echo_count;
@@ -75,7 +75,6 @@ static BOOL push_queued_message(char *buf, int msg_len,
struct timeval end_time,
char *private_data, size_t private_len)
{
- struct pending_message_list *tmp_msg;
struct pending_message_list *msg;
msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
@@ -105,7 +104,7 @@ static BOOL push_queued_message(char *buf, int msg_len,
}
}
- DLIST_ADD_END(deferred_open_queue, msg, tmp_msg);
+ DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
DEBUG(10,("push_message: pushed message length %u on "
"deferred_open_queue\n", (unsigned int)msg_len));
@@ -172,7 +171,6 @@ BOOL open_was_deferred(uint16 mid)
for (pml = deferred_open_queue; pml; pml = pml->next) {
if (SVAL(pml->buf.data,smb_mid) == mid) {
- set_saved_ntstatus(NT_STATUS_OK);
return True;
}
}
@@ -227,7 +225,8 @@ struct idle_event {
void *private_data;
};
-static void idle_event_handler(struct timed_event *te,
+static void idle_event_handler(struct event_context *ctx,
+ struct timed_event *te,
const struct timeval *now,
void *private_data)
{
@@ -242,7 +241,8 @@ static void idle_event_handler(struct timed_event *te,
return;
}
- event->te = add_timed_event(event, timeval_sum(now, &event->interval),
+ event->te = event_add_timed(smbd_event_context(), event,
+ timeval_sum(now, &event->interval),
"idle_event_handler",
idle_event_handler, event);
@@ -269,11 +269,12 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
result->handler = handler;
result->private_data = private_data;
- result->te = add_timed_event(result, timeval_sum(&now, &interval),
+ result->te = event_add_timed(smbd_event_context(), result,
+ timeval_sum(&now, &interval),
"idle_event_handler",
idle_event_handler, result);
if (result->te == NULL) {
- DEBUG(0, ("add_timed_event failed\n"));
+ DEBUG(0, ("event_add_timed failed\n"));
TALLOC_FREE(result);
return NULL;
}
@@ -303,9 +304,6 @@ static void async_processing(fd_set *pfds)
exit_server_cleanly("termination signal");
}
- /* check for async change notify events */
- process_pending_change_notify_queue(0);
-
/* check for sighup processing */
if (reload_after_sighup) {
change_to_root_user();
@@ -352,7 +350,7 @@ The timeout is in milliseconds
static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
{
- fd_set fds;
+ fd_set r_fds, w_fds;
int selrtn;
struct timeval to;
int maxfd = 0;
@@ -416,10 +414,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
}
/*
- * Setup the select read fd set.
+ * Setup the select fd sets.
*/
- FD_ZERO(&fds);
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
/*
* Ensure we process oplock break messages by preference.
@@ -430,9 +429,9 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
* This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
*/
- if (oplock_message_waiting(&fds)) {
+ if (oplock_message_waiting(&r_fds)) {
DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
- async_processing(&fds);
+ async_processing(&r_fds);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
@@ -447,30 +446,44 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
*/
{
- struct timeval tmp;
- struct timeval *tp = get_timed_events_timeout(&tmp);
-
- if (tp) {
- to = timeval_min(&to, tp);
- if (timeval_is_zero(&to)) {
- /* Process a timed event now... */
- run_events();
- }
+ struct timeval now;
+ GetTimeOfDay(&now);
+
+ event_add_to_select_args(smbd_event_context(), &now,
+ &r_fds, &w_fds, &to, &maxfd);
+ }
+
+ if (timeval_is_zero(&to)) {
+ /* Process a timed event now... */
+ if (run_events(smbd_event_context(), 0, NULL, NULL)) {
+ goto again;
}
}
- maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds);
- maxfd = select_on_fd(change_notify_fd(), maxfd, &fds);
- maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds);
+ {
+ int sav;
+ START_PROFILE(smbd_idle);
+
+ maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
+ maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
- selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
+ selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
+ sav = errno;
+
+ END_PROFILE(smbd_idle);
+ errno = sav;
+ }
+
+ if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
+ goto again;
+ }
/* if we get EINTR then maybe we have received an oplock
signal - treat this as select returning 1. This is ugly, but
is the best we can do until the oplock code knows more about
signals */
if (selrtn == -1 && errno == EINTR) {
- async_processing(&fds);
+ async_processing(&r_fds);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
@@ -498,8 +511,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
* sending us an oplock break message. JRA.
*/
- if (oplock_message_waiting(&fds)) {
- async_processing(&fds);
+ if (oplock_message_waiting(&r_fds)) {
+ async_processing(&r_fds);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
@@ -507,7 +520,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
*/
goto again;
}
-
+
return receive_smb(smbd_server_fd(), buffer, 0);
}
@@ -600,7 +613,7 @@ static const struct smb_message_struct {
/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
-/* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
+/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
@@ -885,7 +898,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
pid = sys_getpid();
errno = 0;
- set_saved_ntstatus(NT_STATUS_OK);
last_message = type;
@@ -954,14 +966,14 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
}
if (!change_to_user(conn,session_tag)) {
- return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
+ return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid)));
}
/* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
/* Does it need write permission? */
if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
- return(ERROR_DOS(ERRSRV,ERRaccess));
+ return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED);
}
/* IPC services are limited */
@@ -1025,60 +1037,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
}
/****************************************************************************
- Keep track of the number of running smbd's. This functionality is used to
- 'hard' limit Samba overhead on resource constrained systems.
-****************************************************************************/
-
-static BOOL process_count_update_successful = False;
-
-static int32 increment_smbd_process_count(void)
-{
- int32 total_smbds;
-
- if (lp_max_smbd_processes()) {
- total_smbds = 0;
- if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
- return 1;
- process_count_update_successful = True;
- return total_smbds + 1;
- }
- return 1;
-}
-
-void decrement_smbd_process_count(void)
-{
- int32 total_smbds;
-
- if (lp_max_smbd_processes() && process_count_update_successful) {
- total_smbds = 1;
- tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
- }
-}
-
-static BOOL smbd_process_limit(void)
-{
- int32 total_smbds;
-
- if (lp_max_smbd_processes()) {
-
- /* Always add one to the smbd process count, as exit_server() always
- * subtracts one.
- */
-
- if (!conn_tdb_ctx()) {
- DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
-set. Ignoring max smbd restriction.\n"));
- return False;
- }
-
- total_smbds = increment_smbd_process_count();
- return total_smbds > lp_max_smbd_processes();
- }
- else
- return False;
-}
-
-/****************************************************************************
Process an smb from the client
****************************************************************************/
@@ -1096,8 +1054,8 @@ static void process_smb(char *inbuf, char *outbuf)
deny parameters before doing any parsing of the packet
passed to us by the client. This prevents attacks on our
parsing code from hosts not in the hosts allow list */
- if (smbd_process_limit() ||
- !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
+ if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
+ lp_hostsdeny(-1))) {
/* send a negative session response "not listening on calling name" */
static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
@@ -1160,7 +1118,7 @@ void remove_from_common_flags2(uint32 v)
common_flags2 &= ~v;
}
-void construct_reply_common(char *inbuf,char *outbuf)
+void construct_reply_common(const char *inbuf, char *outbuf)
{
set_message(outbuf,0,0,False);
@@ -1269,24 +1227,18 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
}
/****************************************************************************
- Setup the needed select timeout.
+ Setup the needed select timeout in milliseconds.
****************************************************************************/
static int setup_select_timeout(void)
{
int select_timeout;
- int t;
-
- select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
- select_timeout *= 1000;
- t = change_notify_timeout();
- DEBUG(10, ("change_notify_timeout: %d\n", t));
- if (t != -1)
- select_timeout = MIN(select_timeout, t*1000);
+ select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000);
- if (print_notify_messages_pending())
+ if (print_notify_messages_pending()) {
select_timeout = MIN(select_timeout, 1000);
+ }
return select_timeout;
}
@@ -1475,19 +1427,13 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup()));
* Check to see if we have any blocking locks
* outstanding on the queue.
*/
- process_blocking_lock_queue(t);
+ process_blocking_lock_queue();
/* update printer queue caches if necessary */
update_monitored_printq_cache();
/*
- * Check to see if we have any change notifies
- * outstanding on the queue.
- */
- process_pending_change_notify_queue(t);
-
- /*
* Now we are root, check if the log files need pruning.
* Force a log file check.
*/
@@ -1517,54 +1463,18 @@ char *get_InBuffer(void)
return InBuffer;
}
-void set_InBuffer(char *new_inbuf)
-{
- InBuffer = new_inbuf;
- current_inbuf = InBuffer;
-}
-
char *get_OutBuffer(void)
{
return OutBuffer;
}
-void set_OutBuffer(char *new_outbuf)
-{
- OutBuffer = new_outbuf;
-}
-
-/****************************************************************************
- Free an InBuffer. Checks if not in use by aio system.
- Must have been allocated by NewInBuffer.
-****************************************************************************/
-
-void free_InBuffer(char *inbuf)
-{
- if (!aio_inbuffer_in_use(inbuf)) {
- if (current_inbuf == inbuf) {
- current_inbuf = NULL;
- }
- SAFE_FREE(inbuf);
- }
-}
-
-/****************************************************************************
- Free an OutBuffer. No outbuffers currently stolen by aio system.
- Must have been allocated by NewInBuffer.
-****************************************************************************/
-
-void free_OutBuffer(char *outbuf)
-{
- SAFE_FREE(outbuf);
-}
-
const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
/****************************************************************************
Allocate a new InBuffer. Returns the new and old ones.
****************************************************************************/
-char *NewInBuffer(char **old_inbuf)
+static char *NewInBuffer(char **old_inbuf)
{
char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
if (!new_inbuf) {
@@ -1584,7 +1494,7 @@ char *NewInBuffer(char **old_inbuf)
Allocate a new OutBuffer. Returns the new and old ones.
****************************************************************************/
-char *NewOutBuffer(char **old_outbuf)
+static char *NewOutBuffer(char **old_outbuf)
{
char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
if (!new_outbuf) {
@@ -1637,7 +1547,7 @@ void smbd_process(void)
num_smbs = 0; /* Reset smb counter. */
}
- run_events();
+ run_events(smbd_event_context(), 0, NULL, NULL);
#if defined(DEVELOPER)
clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index 902212eaf1c..bb88957731f 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -238,8 +238,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if (!found)
return(False);
- save_re_uid();
- set_effective_uid(0);
+ become_root_uid_only();
if (strcmp(mnt->mnt_type, "xfs")==0) {
r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
@@ -252,7 +251,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
}
- restore_re_uid();
+ unbecome_root_uid_only();
/* Use softlimit to determine disk space, except when it has been exceeded */
*bsize = D.bsize;
@@ -656,21 +655,20 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if ( ! found )
return(False) ;
- save_re_uid();
- set_effective_uid(0);
+ become_root_uid_only();
#if defined(SUNOS5)
if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
BOOL retval;
DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
- restore_re_uid();
+ unbecome_root_uid_only();
return retval;
}
DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
if((file=sys_open(name, O_RDONLY,0))<0) {
- restore_re_uid();
+ unbecome_root_uid_only();
return(False);
}
command.op = Q_GETQUOTA;
@@ -683,7 +681,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif
- restore_re_uid();
+ unbecome_root_uid_only();
if (ret < 0) {
DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
@@ -843,8 +841,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
euser_id=geteuid();
- save_re_uid();
- set_effective_uid(0);
+ become_root_uid_only();
/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -854,7 +851,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
{
r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
- restore_re_uid();
+ unbecome_root_uid_only();
if (r==-1)
return(False);
@@ -885,7 +882,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
{
r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
- restore_re_uid();
+ unbecome_root_uid_only();
if (r==-1)
{
@@ -919,7 +916,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
else
{
- restore_re_uid();
+ unbecome_root_uid_only();
return(False);
}
@@ -1183,14 +1180,13 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
return False;
#endif
- save_re_uid();
- set_effective_uid(0);
+ become_root_uid_only();
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
BOOL retval;
retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
- restore_re_uid();
+ unbecome_root_uid_only();
return retval;
}
#endif
@@ -1204,7 +1200,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
}
- restore_re_uid();
+ unbecome_root_uid_only();
}
#elif defined(AIX)
/* AIX has both USER and GROUP quotas:
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index f0dc7af9fba..c48bebb0c6c 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -3,7 +3,7 @@
Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Andrew Bartlett 2001
- Copyright (C) Jeremy Allison 1992-2004.
+ Copyright (C) Jeremy Allison 1992-2007.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,134 +37,6 @@ extern struct current_user current_user;
extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
- 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)
-{
- 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)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- switch (*s) {
- case '*':
- case '?':
- case '<':
- case '>':
- case '"':
- return NT_STATUS_OBJECT_NAME_INVALID;
- default:
- *d++ = *s++;
- break;
- }
- } else {
- 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: 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)) {
- 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
@@ -172,15 +44,17 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
set.
****************************************************************************/
-NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+NTSTATUS check_path_syntax_internal(pstring destname,
+ const pstring srcname,
+ BOOL windows_path,
+ BOOL *p_last_component_contains_wcard)
{
char *d = destname;
const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
BOOL start_of_name_component = True;
- unsigned int num_bad_components = 0;
- *p_contains_wcard = False;
+ *p_last_component_contains_wcard = False;
while (*s) {
if (IS_DIRECTORY_SEP(*s)) {
@@ -197,6 +71,8 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
}
start_of_name_component = True;
+ /* New component. */
+ *p_last_component_contains_wcard = False;
continue;
}
@@ -229,36 +105,30 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
}
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 (!windows_path) {
+ /* Eat the '.' */
+ s++;
+ continue;
+ }
}
+
}
if (!(*s & 0x80)) {
- if (*s <= 0x1f) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- if (!*p_contains_wcard) {
+ if (windows_path) {
+ if (*s <= 0x1f) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
switch (*s) {
case '*':
case '?':
case '<':
case '>':
case '"':
- *p_contains_wcard = True;
+ *p_last_component_contains_wcard = True;
break;
default:
break;
@@ -266,7 +136,13 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
}
*d++ = *s++;
} else {
- switch(next_mb_char_size(s)) {
+ size_t siz;
+ /* Get the size of the next MB character. */
+ next_codepoint(s,&siz);
+ switch(siz) {
+ case 5:
+ *d++ = *s++;
+ /*fall through*/
case 4:
*d++ = *s++;
/*fall through*/
@@ -280,124 +156,50 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
*d++ = *s++;
break;
default:
- DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
+ DEBUG(0,("check_path_syntax_internal: 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';
return ret;
}
/****************************************************************************
- Check the path for a POSIX client.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption).
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ No wildcards allowed.
****************************************************************************/
-NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
- char *d = destname;
- const char *s = srcname;
- NTSTATUS ret = NT_STATUS_OK;
- BOOL start_of_name_component = True;
-
- while (*s) {
- if (*s == '/') {
- /*
- * Safe to assume is not the second part of a mb char as this is handled below.
- */
- /* Eat multiple '/' or '\\' */
- while (*s == '/') {
- s++;
- }
- if ((d != destname) && (*s != '\0')) {
- /* We only care about non-leading or trailing '/' */
- *d++ = '/';
- }
-
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
- /* Uh oh - "/../" 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--;
- }
+ BOOL ignore;
+ return check_path_syntax_internal(destname, srcname, True, &ignore);
+}
- /* 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 .. */
- continue;
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ Wildcards allowed - p_contains_wcard returns true if the last component contained
+ a wildcard.
+****************************************************************************/
- } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
- /* Eat the '.' */
- s++;
- continue;
- }
- }
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+{
+ return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
+}
- if (!(*s & 0x80)) {
- *d++ = *s++;
- } else {
- switch(next_mb_char_size(s)) {
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- start_of_name_component = False;
- }
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
- *d = '\0';
- return ret;
+static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+{
+ BOOL ignore;
+ return check_path_syntax_internal(destname, srcname, False, &ignore);
}
/****************************************************************************
@@ -427,6 +229,7 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
} else {
*err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
}
+
return ret;
}
@@ -453,6 +256,7 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
} else {
*err = check_path_syntax(dest, tmppath);
}
+
return ret;
}
@@ -480,7 +284,7 @@ int reply_special(char *inbuf,char *outbuf)
case 0x81: /* session request */
if (already_got_session) {
- exit_server("multiple session request not permitted");
+ exit_server_cleanly("multiple session request not permitted");
}
SCVAL(outbuf,0,0x82);
@@ -792,70 +596,94 @@ int reply_ioctl(connection_struct *conn,
}
/****************************************************************************
- Reply to a chkpth.
+ Strange checkpath NTSTATUS mapping.
****************************************************************************/
-int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
+{
+ /* Strange DOS error code semantics only for checkpath... */
+ if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
+ if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
+ /* We need to map to ERRbadpath */
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+ return status;
+}
+
+/****************************************************************************
+ Reply to a checkpath.
+****************************************************************************/
+
+int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
pstring name;
- BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
- START_PROFILE(SMBchkpth);
+ START_PROFILE(SMBcheckpath);
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBchkpth);
+ END_PROFILE(SMBcheckpath);
+ status = map_checkpath_error(inbuf, status);
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
- unix_convert(name,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
+
+ status = unix_convert(conn, name, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto path_err;
}
- if (check_name(name,conn)) {
- if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
- if (!(ok = S_ISDIR(sbuf.st_mode))) {
- END_PROFILE(SMBchkpth);
- return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
- }
+ status = check_name(conn, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
+ goto path_err;
}
- if (!ok) {
- /* We special case this - as when a Windows machine
- is parsing a path is steps through the components
- one at a time - if a component fails it expects
- ERRbadpath, not ERRbadfile.
- */
- if(errno == ENOENT) {
- /*
- * Windows returns different error codes if
- * the parent directory is valid but not the
- * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
- * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
- * if the path is invalid. This is different from set_bad_path_error()
- * in the non-NT error case.
- */
- END_PROFILE(SMBchkpth);
- return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
- }
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
+ DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ goto path_err;
+ }
- END_PROFILE(SMBchkpth);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ if (!S_ISDIR(sbuf.st_mode)) {
+ END_PROFILE(SMBcheckpath);
+ return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
}
outsize = set_message(outbuf,0,0,False);
- DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
- END_PROFILE(SMBchkpth);
- return(outsize);
+ END_PROFILE(SMBcheckpath);
+ return outsize;
+
+ path_err:
+
+ END_PROFILE(SMBcheckpath);
+
+ /* We special case this - as when a Windows machine
+ is parsing a path is steps through the components
+ one at a time - if a component fails it expects
+ ERRbadpath, not ERRbadfile.
+ */
+ status = map_checkpath_error(inbuf, status);
+ if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ /*
+ * Windows returns different error codes if
+ * the parent directory is valid but not the
+ * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
+ * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
+ * if the path is invalid.
+ */
+ return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
+ }
+
+ return ERROR_NT(status);
}
/****************************************************************************
@@ -867,11 +695,9 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
pstring fname;
int outsize = 0;
SMB_STRUCT_STAT sbuf;
- BOOL ok = False;
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
@@ -888,38 +714,38 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
- if (! (*fname)) {
+ if (*fname == '\0') {
mode = aHIDDEN | aDIR;
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
mode |= aRONLY;
+ }
size = 0;
mtime = 0;
- ok = True;
} else {
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL,&sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
- if (check_name(fname,conn)) {
- if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
- mode = dos_mode(conn,fname,&sbuf);
- size = sbuf.st_size;
- mtime = sbuf.st_mtime;
- if (mode & aDIR)
- size = 0;
- ok = True;
- } else {
- DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
- }
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
+ END_PROFILE(SMBgetatr);
+ return ERROR_NT(status);
+ }
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
+ DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+ return UNIXERROR(ERRDOS,ERRbadfile);
+ }
+
+ mode = dos_mode(conn,fname,&sbuf);
+ size = sbuf.st_size;
+ mtime = sbuf.st_mtime;
+ if (mode & aDIR) {
+ size = 0;
}
}
- if (!ok) {
- END_PROFILE(SMBgetatr);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
- }
-
outsize = set_message(outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
@@ -934,7 +760,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
- DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
+ DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
END_PROFILE(SMBgetatr);
return(outsize);
@@ -948,11 +774,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
{
pstring fname;
int outsize = 0;
- BOOL ok=False;
int mode;
time_t mtime;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
char *p;
NTSTATUS status;
@@ -967,10 +791,25 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
+ }
+
+ if (fname[0] == '.' && fname[1] == '\0') {
+ /*
+ * Not sure here is the right place to catch this
+ * condition. Might be moved to somewhere else later -- vl
+ */
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(status);
}
mode = SVAL(inbuf,smb_vwv0);
@@ -982,19 +821,15 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
else
mode &= ~aDIR;
- if (check_name(fname,conn)) {
- ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
+ if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
+ END_PROFILE(SMBsetatr);
+ return UNIXERROR(ERRDOS, ERRnoaccess);
}
- } else {
- ok = True;
}
- if (ok)
- ok = set_filetime(conn,fname,mtime);
-
- if (!ok) {
+ if (!set_filetime(conn,fname,mtime)) {
END_PROFILE(SMBsetatr);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return UNIXERROR(ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,0,0,False);
@@ -1075,15 +910,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
unsigned int maxentries = 0;
BOOL finished = False;
char *p;
- BOOL ok = False;
int status_len;
pstring path;
char status[21];
int dptr_num= -1;
BOOL check_descend = False;
BOOL expect_close = False;
- BOOL can_open = True;
- BOOL bad_path = False;
NTSTATUS nt_status;
BOOL mask_contains_wcard = False;
BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
@@ -1098,8 +930,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
*mask = *directory = *fname = 0;
/* If we were called as SMBffirst then we must expect close. */
- if(CVAL(inbuf,smb_com) == SMBffirst)
+ if(CVAL(inbuf,smb_com) == SMBffirst) {
expect_close = True;
+ }
outsize = set_message(outbuf,1,3,True);
maxentries = SVAL(inbuf,smb_vwv0);
@@ -1125,11 +958,18 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
pstrcpy(directory,path);
pstrcpy(dir2,path);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
+ nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_NT(nt_status);
+ }
unix_format(dir2);
- if (!check_name(directory,conn))
- can_open = False;
+ nt_status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_NT(nt_status);
+ }
p = strrchr_m(dir2,'/');
if (p == NULL) {
@@ -1141,13 +981,15 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
p = strrchr_m(directory,'/');
- if (!p)
+ if (!p) {
*directory = 0;
- else
+ } else {
*p = 0;
+ }
- if (strlen(directory) == 0)
+ if (strlen(directory) == 0) {
pstrcpy(directory,".");
+ }
memset((char *)status,'\0',21);
SCVAL(status,0,(dirtype & 0x1F));
} else {
@@ -1155,83 +997,85 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
memcpy(status,p,21);
status_dirtype = CVAL(status,0) & 0x1F;
- if (status_dirtype != (dirtype & 0x1F))
+ if (status_dirtype != (dirtype & 0x1F)) {
dirtype = status_dirtype;
+ }
conn->dirptr = dptr_fetch(status+12,&dptr_num);
- if (!conn->dirptr)
+ if (!conn->dirptr) {
goto SearchEmpty;
+ }
string_set(&conn->dirpath,dptr_path(dptr_num));
pstrcpy(mask, dptr_wcard(dptr_num));
}
- if (can_open) {
- p = smb_buf(outbuf) + 3;
- ok = True;
+ p = smb_buf(outbuf) + 3;
- if (status_len == 0) {
- dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
- if (dptr_num < 0) {
- if(dptr_num == -2) {
- END_PROFILE(SMBsearch);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
- }
- END_PROFILE(SMBsearch);
- return ERROR_DOS(ERRDOS,ERRnofids);
- }
+ if (status_len == 0) {
+ nt_status = dptr_create(conn,
+ directory,
+ True,
+ expect_close,
+ SVAL(inbuf,smb_pid),
+ mask,
+ mask_contains_wcard,
+ dirtype,
+ &conn->dirptr);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return ERROR_NT(nt_status);
+ }
+ dptr_num = dptr_dnum(conn->dirptr);
+ } else {
+ dirtype = dptr_attr(dptr_num);
+ }
+
+ DEBUG(4,("dptr_num is %d\n",dptr_num));
+
+ if ((dirtype&0x1F) == aVOLID) {
+ memcpy(p,status,21);
+ 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;
} else {
- dirtype = dptr_attr(dptr_num);
+ numentries = 0;
}
+ p += DIR_STRUCT_SIZE;
+ } else {
+ unsigned int i;
+ maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
- DEBUG(4,("dptr_num is %d\n",dptr_num));
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
+ conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
+ check_descend = True;
+ }
- if (ok) {
- if ((dirtype&0x1F) == aVOLID) {
+ for (i=numentries;(i<maxentries) && !finished;i++) {
+ finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
+ if (!finished) {
memcpy(p,status,21);
- 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;
- else
- numentries = 0;
- p += DIR_STRUCT_SIZE;
- } else {
- unsigned int i;
- maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
-
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- conn->dirpath,lp_dontdescend(SNUM(conn))));
- if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
- check_descend = True;
-
- for (i=numentries;(i<maxentries) && !finished;i++) {
- 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,
- !allow_long_path_components);
- if (!dptr_fill(p+12,dptr_num)) {
- break;
- }
- numentries++;
- p += DIR_STRUCT_SIZE;
- }
+ make_dir_struct(p,mask,fname,size, mode,date,
+ !allow_long_path_components);
+ if (!dptr_fill(p+12,dptr_num)) {
+ break;
}
+ numentries++;
+ p += DIR_STRUCT_SIZE;
}
- } /* if (ok ) */
+ }
}
-
SearchEmpty:
/* If we were called as SMBffirst with smb_search_id == NULL
and no entries were found then return error and close dirptr
(X/Open spec) */
- if (numentries == 0 || !ok) {
+ if (numentries == 0) {
dptr_close(&dptr_num);
- } else if(ok && expect_close && status_len == 0) {
+ } else if(expect_close && status_len == 0) {
/* Close the dptr - we know it's gone */
dptr_close(&dptr_num);
}
@@ -1339,7 +1183,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
time_t mtime=0;
int info;
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int deny_mode;
@@ -1361,34 +1204,34 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
&access_mask, &share_mode, &create_disposition, &create_options)) {
END_PROFILE(SMBopen);
- return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
+ return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
}
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
create_options,
dos_attr,
oplock_request,
- &info);
+ &info, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return ERROR_NT(status);
}
size = sbuf.st_size;
@@ -1444,12 +1287,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
- SMB_OFF_T size=0;
uint32 fattr=0;
int mtime=0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
- BOOL bad_path = False;
files_struct *fsp;
NTSTATUS status;
SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
@@ -1481,10 +1322,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
@@ -1493,29 +1334,27 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
&create_disposition,
&create_options)) {
END_PROFILE(SMBopenX);
- return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
+ return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
}
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
create_options,
smb_attr,
oplock_request,
- &smb_action);
+ &smb_action, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return ERROR_NT(status);
}
- 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) {
@@ -1531,7 +1370,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
END_PROFILE(SMBopenX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
- size = get_allocation_size(conn,fsp,&sbuf);
+ sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
}
fattr = dos_mode(conn,fname,&sbuf);
@@ -1580,7 +1419,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
} else {
srv_put_dos_date3(outbuf,smb_vwv4,mtime);
}
- SIVAL(outbuf,smb_vwv6,(uint32)size);
+ SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
SSVAL(outbuf,smb_vwv11,smb_action);
@@ -1631,7 +1470,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int com;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- BOOL bad_path = False;
+ struct utimbuf times;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
@@ -1645,6 +1484,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
com = SVAL(inbuf,smb_com);
+ times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
+
srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
@@ -1653,10 +1494,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
if (fattr & aVOLID) {
@@ -1672,24 +1513,27 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
/* Open file using ntcreate. */
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
create_options,
fattr,
oplock_request,
- NULL);
+ NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return ERROR_NT(status);
}
+ times.actime = sbuf.st_atime;
+ file_utime(conn, fname, &times);
+
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
@@ -1717,7 +1561,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring fname;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
int tmpfd;
@@ -1741,10 +1584,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
tmpfd = smb_mkstemp(fname);
@@ -1756,25 +1599,25 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_VFS_STAT(conn,fname,&sbuf);
/* We should fail if file does not exist. */
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
fattr,
oplock_request,
- NULL);
+ NULL, &fsp);
/* close fd from smb_mkstemp() */
close(tmpfd);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+ return ERROR_NT(status);
}
outsize = set_message(outbuf,1,0,True);
@@ -1822,6 +1665,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
{
files_struct *fsp;
uint32 fmode;
+ NTSTATUS status;
if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -1836,26 +1680,17 @@ 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... */
- set_saved_ntstatus(NT_STATUS_OK);
-
- fsp = open_file_ntcreate(conn, fname, pst,
+ status = open_file_ntcreate(conn, fname, pst,
DELETE_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
0,
- NULL);
+ NULL, &fsp);
- if (!fsp) {
- NTSTATUS ret = get_saved_ntstatus();
- if (!NT_STATUS_IS_OK(ret)) {
- set_saved_ntstatus(NT_STATUS_OK);
- return ret;
- }
- set_saved_ntstatus(NT_STATUS_OK);
- return NT_STATUS_ACCESS_DENIED;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
close_file(fsp,NORMAL_CLOSE);
return NT_STATUS_OK;
@@ -1865,11 +1700,14 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
Check if a user is allowed to delete a file.
********************************************************************/
-NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open, BOOL can_defer)
+static NTSTATUS can_delete(connection_struct *conn, char *fname,
+ uint32 dirtype, BOOL can_defer)
{
SMB_STRUCT_STAT sbuf;
uint32 fattr;
files_struct *fsp;
+ uint32 dirtype_orig = dirtype;
+ NTSTATUS status;
DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
@@ -1878,22 +1716,56 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
}
if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
- 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);
}
fattr = dos_mode(conn,fname,&sbuf);
+ if (dirtype & FILE_ATTRIBUTE_NORMAL) {
+ dirtype = aDIR|aARCH|aRONLY;
+ }
+
+ dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!dir_check_ftype(conn, fattr, dirtype)) {
+ if (fattr & aDIR) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype_orig & 0x8000) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+#if 0
+ if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (dirtype & 0xFF00) {
+ /* These will never be set for POSIX. */
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ dirtype &= 0xFF;
+ if (!dirtype) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
/* Can't delete a directory. */
if (fattr & aDIR) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
+#endif
#if 0 /* JRATEST */
else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
@@ -1912,47 +1784,28 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
from Windows Explorer).
*/
- if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
+ if (!lp_delete_readonly(SNUM(conn))) {
if (fattr & aRONLY) {
return NT_STATUS_CANNOT_DELETE;
}
}
- if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
- return NT_STATUS_NO_SUCH_FILE;
- }
- if (check_is_at_open) {
- if (!can_delete_file_in_directory(conn, fname)) {
- return NT_STATUS_ACCESS_DENIED;
- }
- } else {
- /* On open checks the open itself will check the share mode, so
- don't do it here as we'll get it wrong. */
-
- /* We need a better way to return NT status codes from open... */
- set_saved_ntstatus(NT_STATUS_OK);
-
- fsp = open_file_ntcreate(conn, fname, &sbuf,
- DELETE_ACCESS,
- FILE_SHARE_NONE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- can_defer ? 0 : INTERNAL_OPEN_ONLY,
- NULL);
-
- if (!fsp) {
- NTSTATUS ret = get_saved_ntstatus();
- if (!NT_STATUS_IS_OK(ret)) {
- set_saved_ntstatus(NT_STATUS_OK);
- return ret;
- }
- set_saved_ntstatus(NT_STATUS_OK);
- return NT_STATUS_ACCESS_DENIED;
- }
+ /* On open checks the open itself will check the share mode, so
+ don't do it here as we'll get it wrong. */
+
+ status = open_file_ntcreate(conn, fname, &sbuf,
+ DELETE_ACCESS,
+ FILE_SHARE_NONE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ can_defer ? 0 : INTERNAL_OPEN_ONLY,
+ NULL, &fsp);
+
+ if (NT_STATUS_IS_OK(status)) {
close_file(fsp,NORMAL_CLOSE);
}
- return NT_STATUS_OK;
+ return status;
}
/****************************************************************************
@@ -1960,20 +1813,22 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
code.
****************************************************************************/
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild, BOOL can_defer)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
+ char *name, BOOL has_wild, BOOL can_defer)
{
pstring directory;
pstring mask;
char *p;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL bad_path = False;
- BOOL rc = True;
+ NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf;
*directory = *mask = 0;
- rc = unix_convert(name,conn,0,&bad_path,&sbuf);
+ status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
p = strrchr_m(name,'/');
if (!p) {
@@ -1994,87 +1849,99 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask,SNUM(conn)))
- mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+ if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
+ mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- error = can_delete(conn,directory,dirtype,bad_path,False,can_defer);
- if (!NT_STATUS_IS_OK(error))
- return error;
+ if (dirtype == 0) {
+ dirtype = FILE_ATTRIBUTE_NORMAL;
+ }
+ status = can_delete(conn,directory,dirtype,can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (SMB_VFS_UNLINK(conn,directory) == 0) {
count++;
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ directory);
}
} else {
struct smb_Dir *dir_hnd = NULL;
+ long offset = 0;
const char *dname;
- if (strequal(mask,"????????.???"))
+ if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+
+ if (strequal(mask,"????????.???")) {
pstrcpy(mask,"*");
+ }
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, dirtype);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ dir_hnd = OpenDir(conn, directory, mask, dirtype);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name, otherwise the short name
We don't implement this yet XXXX
*/
- if (dir_hnd) {
- long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
+ status = NT_STATUS_NO_SUCH_FILE;
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- SMB_STRUCT_STAT st;
- pstring fname;
- BOOL sys_direntry = False;
- pstrcpy(fname,dname);
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ SMB_STRUCT_STAT st;
+ pstring fname;
+ pstrcpy(fname,dname);
- if (!is_visible_file(conn, directory, dname, &st, True)) {
- continue;
- }
-
- /* Quick check for "." and ".." */
- if (fname[0] == '.') {
- if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
- sys_direntry = True;
- } else {
- continue;
- }
- }
- }
+ if (!is_visible_file(conn, directory, dname, &st, True)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
+ /* Quick check for "." and ".." */
+ if (fname[0] == '.') {
+ if (!fname[1] || (fname[1] == '.' && !fname[2])) {
continue;
-
- if (sys_direntry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
- DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
- fname, mask));
- break;
}
+ }
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- error = can_delete(conn,fname,dirtype,bad_path,False,False);
- if (!NT_STATUS_IS_OK(error)) {
- continue;
- }
- if (SMB_VFS_UNLINK(conn,fname) == 0)
- count++;
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
+
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+ status = can_delete(conn, fname, dirtype, can_defer);
+ if (!NT_STATUS_IS_OK(status)) {
+ continue;
}
- CloseDir(dir_hnd);
+ if (SMB_VFS_UNLINK(conn,fname) == 0) {
+ count++;
+ DEBUG(3,("unlink_internals: succesful unlink "
+ "[%s]\n",fname));
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ fname);
+ }
+
}
+ CloseDir(dir_hnd);
}
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- return error;
+ return status;
}
/****************************************************************************
@@ -2104,7 +1971,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
DEBUG(3,("reply_unlink : %s\n",name));
- status = unlink_internals(conn, dirtype, name, path_contains_wcard, True);
+ status = unlink_internals(conn, dirtype, name, path_contains_wcard,
+ True);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
@@ -2113,12 +1981,6 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
- process_pending_change_notify_queue((time_t)0);
-
outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBunlink);
@@ -2134,7 +1996,7 @@ static void fail_readraw(void)
pstring errstr;
slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
strerror(errno) );
- exit_server(errstr);
+ exit_server_cleanly(errstr);
}
#if defined(WITH_SENDFILE)
@@ -2216,14 +2078,14 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readbraw fake_sendfile failed");
+ exit_server_cleanly("send_file_readbraw fake_sendfile failed");
}
return;
}
DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readbraw sendfile failed");
+ exit_server_cleanly("send_file_readbraw sendfile failed");
}
}
@@ -2262,7 +2124,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
START_PROFILE(SMBreadbraw);
if (srv_is_signing_active()) {
- exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
+ exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
}
/*
@@ -2331,7 +2193,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
/* ensure we don't overrun the packet size */
maxcount = MIN(65535,maxcount);
- if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
SMB_STRUCT_STAT st;
SMB_OFF_T size = 0;
@@ -2377,7 +2239,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
size_t numtoread;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- BOOL my_lock_ctx = False;
+ struct byte_range_lock *br_lck = NULL;
START_PROFILE(SMBlockread);
CHECK_FSP(fsp,conn);
@@ -2402,42 +2264,17 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* Note that the requested lock size is unaffected by max_recv.
*/
- status = do_lock_spin(fsp,
- SVAL(inbuf,smb_pid),
- (SMB_BIG_UINT)numtoread,
- (SMB_BIG_UINT)startpos,
- WRITE_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
+ br_lck = do_lock(fsp,
+ (uint32)SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtoread,
+ (SMB_BIG_UINT)startpos,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ False, /* Non-blocking lock. */
+ &status);
+ TALLOC_FREE(br_lck);
if (NT_STATUS_V(status)) {
-#if 0
- /*
- * We used to make lockread a blocking lock. It turns out
- * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
- * tester. JRA.
- */
-
- if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length,
- fsp,
- -1,
- 0,
- SVAL(inbuf,smb_pid),
- WRITE_LOCK,
- WINDOWS_LOCK,
- (SMB_BIG_UINT)startpos,
- (SMB_BIG_UINT)numtoread)) {
- END_PROFILE(SMBlockread);
- return -1;
- }
- }
-#endif
END_PROFILE(SMBlockread);
return ERROR_NT(status);
}
@@ -2510,7 +2347,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
data = smb_buf(outbuf) + 3;
- if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBread);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2609,7 +2446,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
len_outbuf - (data-outbuf))) == -1) {
DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readX: fake_sendfile failed");
+ exit_server_cleanly("send_file_readX: fake_sendfile failed");
}
DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
fsp->fnum, (int)smb_maxcnt, (int)nread ) );
@@ -2619,7 +2456,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readX sendfile failed");
+ exit_server_cleanly("send_file_readX sendfile failed");
}
DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
@@ -2717,7 +2554,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
- if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadX);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2753,7 +2590,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
START_PROFILE(SMBwritebraw);
if (srv_is_signing_active()) {
- exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
+ exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
}
CHECK_FSP(fsp,conn);
@@ -2780,7 +2617,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
SCVAL(inbuf,smb_com,SMBwritec);
SCVAL(outbuf,smb_com,SMBwritec);
- if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwritebraw);
return(ERROR_DOS(ERRDOS,ERRlock));
}
@@ -2804,11 +2641,11 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_writebraw: send_smb failed.");
+ exit_server_cleanly("reply_writebraw: send_smb failed.");
/* Now read the raw data into the buffer and write it */
if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
- exit_server("secondary writebraw failed");
+ exit_server_cleanly("secondary writebraw failed");
}
/* Even though this is not an smb message, smb_len returns the generic length of an smb message */
@@ -2823,7 +2660,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
if (numtowrite > BUFFER_SIZE) {
DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
(unsigned int)numtowrite ));
- exit_server("secondary writebraw failed");
+ exit_server_cleanly("secondary writebraw failed");
}
if (tcount > nwritten+numtowrite) {
@@ -2834,10 +2671,14 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
strerror(errno) ));
- exit_server("secondary writebraw failed");
+ exit_server_cleanly("secondary writebraw failed");
}
nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
+ if (nwritten == -1) {
+ END_PROFILE(SMBwritebraw);
+ return(UNIXERROR(ERRHRD,ERRdiskfull));
+ }
if (nwritten < (ssize_t)numtowrite) {
SCVAL(outbuf,smb_rcls,ERRHRD);
@@ -2865,7 +2706,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
* sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
*/
if (!send_keepalive(smbd_server_fd()))
- exit_server("reply_writebraw: send of keepalive failed");
+ exit_server_cleanly("reply_writebraw: send of keepalive failed");
#endif
return(-1);
}
@@ -2901,7 +2742,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
data = smb_buf(inbuf) + 3;
- if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteunlock);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2924,7 +2765,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
if (numtowrite) {
status = do_unlock(fsp,
- SVAL(inbuf,smb_pid),
+ (uint32)SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtowrite,
(SMB_BIG_UINT)startpos,
WINDOWS_LOCK);
@@ -2978,7 +2819,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
data = smb_buf(inbuf) + 3;
- if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwrite);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3093,7 +2934,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
#endif /* LARGE_SMB_OFF_T */
}
- if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteX);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3266,9 +3107,9 @@ int reply_exit(connection_struct *conn,
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
+ NTSTATUS status = NT_STATUS_OK;
int outsize = 0;
time_t mtime;
- int32 eclass = 0, err = 0;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
@@ -3295,17 +3136,12 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
/*
* Special case - close NT SMB directory handle.
*/
- DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
- close_file(fsp,NORMAL_CLOSE);
+ DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
+ status = close_file(fsp,NORMAL_CLOSE);
} else {
/*
* Close ordinary file.
*/
- int close_err;
- pstring file_name;
-
- /* Save the name for time set in close. */
- pstrcpy( file_name, fsp->fsp_name);
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
fsp->fh->fd, fsp->fnum,
@@ -3324,17 +3160,12 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
* a disk full error. If not then it was probably an I/O error.
*/
- if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
- errno = close_err;
- END_PROFILE(SMBclose);
- return (UNIXERROR(ERRHRD,ERRgeneral));
- }
+ status = close_file(fsp,NORMAL_CLOSE);
}
- /* We have a cached error */
- if(eclass || err) {
+ if(!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBclose);
- return ERROR_DOS(eclass,err);
+ return ERROR_NT(status);
}
END_PROFILE(SMBclose);
@@ -3351,7 +3182,7 @@ int reply_writeclose(connection_struct *conn,
size_t numtowrite;
ssize_t nwritten = -1;
int outsize = 0;
- int close_err = 0;
+ NTSTATUS close_status = NT_STATUS_OK;
SMB_OFF_T startpos;
char *data;
time_t mtime;
@@ -3368,7 +3199,7 @@ int reply_writeclose(connection_struct *conn,
mtime = srv_make_unix_date3(inbuf+smb_vwv4);
data = smb_buf(inbuf) + 1;
- if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteclose);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3385,7 +3216,7 @@ int reply_writeclose(connection_struct *conn,
if (numtowrite) {
DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
fsp->fsp_name ));
- close_err = close_file(fsp,NORMAL_CLOSE);
+ close_status = close_file(fsp,NORMAL_CLOSE);
}
DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
@@ -3397,10 +3228,9 @@ int reply_writeclose(connection_struct *conn,
return(UNIXERROR(ERRHRD,ERRdiskfull));
}
- if(close_err != 0) {
- errno = close_err;
+ if(!NT_STATUS_IS_OK(close_status)) {
END_PROFILE(SMBwriteclose);
- return(UNIXERROR(ERRHRD,ERRgeneral));
+ return ERROR_NT(close_status);
}
outsize = set_message(outbuf,1,0,True);
@@ -3424,7 +3254,7 @@ int reply_lock(connection_struct *conn,
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- BOOL my_lock_ctx = False;
+ struct byte_range_lock *br_lck = NULL;
START_PROFILE(SMBlock);
@@ -3438,35 +3268,18 @@ int reply_lock(connection_struct *conn,
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
- status = do_lock_spin(fsp,
- SVAL(inbuf,smb_pid),
- count,
- offset,
- WRITE_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
+ br_lck = do_lock(fsp,
+ (uint32)SVAL(inbuf,smb_pid),
+ count,
+ offset,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ False, /* Non-blocking lock. */
+ &status);
+
+ TALLOC_FREE(br_lck);
+
if (NT_STATUS_V(status)) {
-#if 0
- /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
- if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length,
- fsp,
- -1,
- 0,
- SVAL(inbuf,smb_pid),
- WRITE_LOCK,
- WINDOWS_LOCK,
- offset, count)) {
- END_PROFILE(SMBlock);
- return -1;
- }
- }
-#endif
END_PROFILE(SMBlock);
return ERROR_NT(status);
}
@@ -3494,7 +3307,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
status = do_unlock(fsp,
- SVAL(inbuf,smb_pid),
+ (uint32)SVAL(inbuf,smb_pid),
count,
offset,
WINDOWS_LOCK);
@@ -3578,7 +3391,7 @@ int reply_echo(connection_struct *conn,
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_echo: send_smb failed.");
+ exit_server_cleanly("reply_echo: send_smb failed.");
}
DEBUG(3,("echo %d times\n", smb_reverb));
@@ -3598,6 +3411,8 @@ int reply_printopen(connection_struct *conn,
{
int outsize = 0;
files_struct *fsp;
+ NTSTATUS status;
+
START_PROFILE(SMBsplopen);
if (!CAN_PRINT(conn)) {
@@ -3606,11 +3421,11 @@ int reply_printopen(connection_struct *conn,
}
/* Open for exclusive use, write only. */
- fsp = print_fsp_open(conn, NULL);
+ status = print_fsp_open(conn, NULL, &fsp);
- if (!fsp) {
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsplopen);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return(ERROR_NT(status));
}
outsize = set_message(outbuf,1,0,True);
@@ -3632,25 +3447,24 @@ int reply_printclose(connection_struct *conn,
{
int outsize = set_message(outbuf,0,0,False);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int close_err = 0;
+ NTSTATUS status;
START_PROFILE(SMBsplclose);
CHECK_FSP(fsp,conn);
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplclose);
- return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
}
DEBUG(3,("printclose fd=%d fnum=%d\n",
fsp->fh->fd,fsp->fnum));
- close_err = close_file(fsp,NORMAL_CLOSE);
+ status = close_file(fsp,NORMAL_CLOSE);
- if(close_err != 0) {
- errno = close_err;
+ if(!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsplclose);
- return(UNIXERROR(ERRHRD,ERRgeneral));
+ return ERROR_NT(status);
}
END_PROFILE(SMBsplclose);
@@ -3766,47 +3580,6 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
}
/****************************************************************************
- The guts of the mkdir command, split out so it may be called by the NT SMB
- code.
-****************************************************************************/
-
-NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
-{
- int ret= -1;
-
- 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)) {
- 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;
- }
- return map_nt_error_from_unix(errno);
- }
-
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
Reply to a mkdir.
****************************************************************************/
@@ -3815,7 +3588,6 @@ 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);
@@ -3828,36 +3600,31 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
-
- if( is_ntfs_stream_name(directory)) {
- DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
- END_PROFILE(SMBmkdir);
- return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
- }
-
- status = mkdir_internal(conn, directory,bad_path);
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
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. */
+ status = create_directory(conn, directory);
- 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));
+ DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
+
+ if (!NT_STATUS_IS_OK(status)) {
+
+ if (!use_nt_status()
+ && NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
+ /*
+ * Yes, in the DOS error code case we get a
+ * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
+ * samba4 torture test.
+ */
+ status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
}
- change_owner_to_parent(conn, NULL, directory, &sbuf);
+ END_PROFILE(SMBmkdir);
+ return ERROR_NT(status);
}
outsize = set_message(outbuf,0,0,False);
@@ -3870,18 +3637,18 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/****************************************************************************
Static function used by reply_rmdir to delete an entire directory
- tree recursively. Return False on ok, True on fail.
+ tree recursively. Return True on ok, False on fail.
****************************************************************************/
static BOOL recursive_rmdir(connection_struct *conn, char *directory)
{
const char *dname = NULL;
- BOOL ret = False;
+ BOOL ret = True;
long offset = 0;
struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
if(dir_hnd == NULL)
- return True;
+ return False;
while((dname = ReadDirName(dir_hnd, &offset))) {
pstring fullname;
@@ -3896,7 +3663,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
/* Construct the full name. */
if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
errno = ENOMEM;
- ret = True;
+ ret = False;
break;
}
@@ -3905,21 +3672,21 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
pstrcat(fullname, dname);
if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
- ret = True;
+ ret = False;
break;
}
if(st.st_mode & S_IFDIR) {
- if(recursive_rmdir(conn, fullname)!=0) {
- ret = True;
+ if(!recursive_rmdir(conn, fullname)) {
+ ret = False;
break;
}
if(SMB_VFS_RMDIR(conn,fullname) != 0) {
- ret = True;
+ ret = False;
break;
}
} else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
- ret = True;
+ ret = False;
break;
}
}
@@ -3931,83 +3698,98 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
The internals of the rmdir code - called elsewhere.
****************************************************************************/
-BOOL rmdir_internals(connection_struct *conn, char *directory)
+NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
{
- BOOL ok;
+ int ret;
SMB_STRUCT_STAT st;
- ok = (SMB_VFS_RMDIR(conn,directory) == 0);
- if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
+ ret = SMB_VFS_RMDIR(conn,directory);
+ if (ret == 0) {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+ return NT_STATUS_OK;
+ }
+
+ if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
/*
* Check to see if the only thing in this directory are
* vetoed files/directories. If so then delete them and
* retry. If we fail to delete any of them (and we *don't*
* do a recursive delete) then fail the rmdir.
*/
- BOOL all_veto_files = True;
const char *dname;
+ long dirpos = 0;
struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
- if(dir_hnd != NULL) {
- long dirpos = 0;
- while ((dname = ReadDirName(dir_hnd,&dirpos))) {
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
- if (!is_visible_file(conn, directory, dname, &st, False))
- continue;
- if(!IS_VETO_PATH(conn, dname)) {
- all_veto_files = False;
- break;
- }
+ if(dir_hnd == NULL) {
+ errno = ENOTEMPTY;
+ goto err;
+ }
+
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
+ if(!IS_VETO_PATH(conn, dname)) {
+ CloseDir(dir_hnd);
+ errno = ENOTEMPTY;
+ goto err;
}
+ }
- if(all_veto_files) {
- RewindDir(dir_hnd,&dirpos);
- while ((dname = ReadDirName(dir_hnd,&dirpos))) {
- pstring fullname;
+ /* We only have veto files/directories. Recursive delete. */
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
- if (!is_visible_file(conn, directory, dname, &st, False))
- continue;
+ RewindDir(dir_hnd,&dirpos);
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
+ pstring fullname;
- /* Construct the full name. */
- if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
- errno = ENOMEM;
- break;
- }
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
- pstrcpy(fullname, directory);
- pstrcat(fullname, "/");
- pstrcat(fullname, dname);
-
- if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
- break;
- if(st.st_mode & S_IFDIR) {
- if(lp_recursive_veto_delete(SNUM(conn))) {
- if(recursive_rmdir(conn, fullname) != 0)
- break;
- }
- if(SMB_VFS_RMDIR(conn,fullname) != 0)
- break;
- } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
+ /* Construct the full name. */
+ if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+ errno = ENOMEM;
+ break;
+ }
+
+ pstrcpy(fullname, directory);
+ pstrcat(fullname, "/");
+ pstrcat(fullname, dname);
+
+ if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
+ break;
+ if(st.st_mode & S_IFDIR) {
+ if(lp_recursive_veto_delete(SNUM(conn))) {
+ if(!recursive_rmdir(conn, fullname))
break;
}
- CloseDir(dir_hnd);
- /* Retry the rmdir */
- ok = (SMB_VFS_RMDIR(conn,directory) == 0);
- } else {
- CloseDir(dir_hnd);
- }
- } else {
- errno = ENOTEMPTY;
+ if(SMB_VFS_RMDIR(conn,fullname) != 0)
+ break;
+ } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
+ break;
}
+ CloseDir(dir_hnd);
+ /* Retry the rmdir */
+ ret = SMB_VFS_RMDIR(conn,directory);
}
- if (!ok)
- DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
+ err:
+
+ if (ret != 0) {
+ DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
+ "%s\n", directory,strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
- return ok;
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -4018,8 +3800,6 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
{
pstring directory;
int outsize = 0;
- BOOL ok = False;
- BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBrmdir);
@@ -4032,20 +3812,23 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
- unix_convert(directory,conn, NULL,&bad_path,&sbuf);
- if (bad_path) {
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ return ERROR_NT(status);
}
- if (check_name(directory,conn)) {
- dptr_closepath(directory,SVAL(inbuf,smb_pid));
- ok = rmdir_internals(conn, directory);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBrmdir);
+ return ERROR_NT(status);
}
-
- if (!ok) {
+
+ dptr_closepath(directory,SVAL(inbuf,smb_pid));
+ status = rmdir_internals(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
+ return ERROR_NT(status);
}
outsize = set_message(outbuf,0,0,False);
@@ -4210,27 +3993,19 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest)
Rename an open file - given an fsp.
****************************************************************************/
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
{
SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
pstring newname_last_component;
- NTSTATUS error = NT_STATUS_OK;
+ NTSTATUS status = NT_STATUS_OK;
BOOL dest_exists;
- BOOL rcdest = True;
struct share_mode_lock *lck = NULL;
ZERO_STRUCT(sbuf);
- rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
- /* Quick check for "." and ".." */
- if (!bad_path && newname_last_component[0] == '.') {
- if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
- return NT_STATUS_ACCESS_DENIED;
- }
- }
- if (!rcdest && bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Ensure newname contains a '/' */
@@ -4292,14 +4067,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- error = can_rename(conn,newname,attrs,&sbuf);
+ status = can_rename(conn,newname,attrs,&sbuf);
- if (dest_exists && !NT_STATUS_IS_OK(error)) {
+ if (dest_exists && !NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
- if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
- error = NT_STATUS_ACCESS_DENIED;
- return error;
+ nt_errstr(status), fsp->fsp_name,newname));
+ if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
+ status = NT_STATUS_ACCESS_DENIED;
+ return status;
}
if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
@@ -4319,15 +4094,57 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
TALLOC_FREE(lck);
if (errno == ENOTDIR || errno == EISDIR) {
- error = NT_STATUS_OBJECT_NAME_COLLISION;
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
} else {
- error = map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
}
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
- nt_errstr(error), fsp->fsp_name,newname));
+ nt_errstr(status), fsp->fsp_name,newname));
- return error;
+ return status;
+}
+
+/*
+ * Do the notify calls from a rename
+ */
+
+static void notify_rename(connection_struct *conn, BOOL is_dir,
+ const char *oldpath, const char *newpath)
+{
+ char *olddir, *newdir;
+ const char *oldname, *newname;
+ uint32 mask;
+
+ mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
+ : FILE_NOTIFY_CHANGE_FILE_NAME;
+
+ if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
+ || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
+ TALLOC_FREE(olddir);
+ return;
+ }
+
+ if (strcmp(olddir, newdir) == 0) {
+ notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
+ }
+ else {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
+ }
+ TALLOC_FREE(olddir);
+ TALLOC_FREE(newdir);
+
+ /* this is a strange one. w2k3 gives an additional event for
+ CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
+ files, but not directories */
+ if (!is_dir) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES
+ |FILE_NOTIFY_CHANGE_CREATION,
+ newpath);
+ }
}
/****************************************************************************
@@ -4335,19 +4152,17 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
+NTSTATUS rename_internals(connection_struct *conn, pstring name,
+ pstring newname, uint32 attrs,
+ BOOL replace_if_exists, BOOL has_wild)
{
pstring directory;
pstring mask;
pstring last_component_src;
pstring last_component_dest;
char *p;
- BOOL bad_path_src = False;
- BOOL bad_path_dest = False;
int count=0;
- NTSTATUS error = NT_STATUS_OK;
- BOOL rc = True;
- BOOL rcdest = True;
+ NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf1, sbuf2;
struct share_mode_lock *lck = NULL;
@@ -4356,27 +4171,16 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
- if (!rc && bad_path_src) {
- if (ms_has_wild(last_component_src))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_src[0] == '.') {
- if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, name, has_wild, last_component_src,
+ &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
-
- /* Quick check for "." and ".." */
- if (last_component_dest[0] == '.') {
- if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, True, last_component_dest,
+ &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
@@ -4408,14 +4212,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask,SNUM(conn)))
- mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+ mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
if (!has_wild) {
/*
* No wildcards - just process the one file.
*/
- BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
+ BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
/* Add a terminating '/' to the directory name. */
pstrcat(directory,"/");
@@ -4430,10 +4234,13 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
pstrcpy(newname, tmpstr);
}
- DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
-directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
- conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
- newname, last_component_dest, is_short_name));
+ DEBUG(3, ("rename_internals: case_sensitive = %d, "
+ "case_preserve = %d, short case preserve = %d, "
+ "directory = %s, newname = %s, "
+ "last_component_dest = %s, is_8_3 = %d\n",
+ conn->case_sensitive, conn->case_preserve,
+ conn->short_case_preserve, directory,
+ newname, last_component_dest, is_short_name));
/*
* Check for special case with case preserving and not
@@ -4476,13 +4283,16 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
*/
if (!vfs_object_exist(conn, directory, &sbuf1)) {
- DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
+ DEBUG(3, ("rename_internals: source doesn't exist "
+ "doing rename %s -> %s\n",
directory,newname));
- if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
+ if (errno == ENOTDIR || errno == EISDIR
+ || errno == ENOENT) {
/*
- * Must return different errors depending on whether the parent
- * directory existed or not.
+ * Must return different errors depending on
+ * whether the parent directory existed or
+ * not.
*/
p = strrchr_m(directory, '/');
@@ -4493,25 +4303,21 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- error = map_nt_error_from_unix(errno);
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ status = map_nt_error_from_unix(errno);
+ DEBUG(3, ("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
- return error;
+ return status;
}
- if (!rcdest && bad_path_dest) {
- if (ms_has_wild(last_component_dest))
- return NT_STATUS_OBJECT_NAME_INVALID;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- error = can_rename(conn,directory,attrs,&sbuf1);
+ status = can_rename(conn,directory,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
- DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
- return error;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
+ return status;
}
/*
@@ -4520,14 +4326,17 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
*/
if (strcsequal(directory, newname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
+ rename_open_files(conn, NULL, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ DEBUG(3, ("rename_internals: identical names in "
+ "rename %s - returning success\n",
+ directory));
return NT_STATUS_OK;
}
if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
- DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
- directory,newname));
+ DEBUG(3,("rename_internals: dest exists doing "
+ "rename %s -> %s\n", directory, newname));
return NT_STATUS_OBJECT_NAME_COLLISION;
}
@@ -4535,125 +4344,153 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_SHARING_VIOLATION;
}
- lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
+ NULL, NULL);
if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
- DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
- directory,newname));
- rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: succeeded doing rename "
+ "on %s -> %s\n", directory, newname));
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
TALLOC_FREE(lck);
+ notify_rename(conn, S_ISDIR(sbuf1.st_mode),
+ directory, newname);
return NT_STATUS_OK;
}
TALLOC_FREE(lck);
- if (errno == ENOTDIR || errno == EISDIR)
- error = NT_STATUS_OBJECT_NAME_COLLISION;
- else
- error = map_nt_error_from_unix(errno);
+ if (errno == ENOTDIR || errno == EISDIR) {
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ } else {
+ status = map_nt_error_from_unix(errno);
+ }
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ nt_errstr(status), directory,newname));
- return error;
+ return status;
} else {
/*
* Wildcards - process each file that matches.
*/
struct smb_Dir *dir_hnd = NULL;
const char *dname;
+ long offset = 0;
pstring destname;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, attrs);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ dir_hnd = OpenDir(conn, directory, mask, attrs);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
- if (dir_hnd) {
- long offset = 0;
- error = NT_STATUS_NO_SUCH_FILE;
-/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
+ status = NT_STATUS_NO_SUCH_FILE;
+ /*
+ * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ * - gentest fix. JRA
+ */
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- pstring fname;
- BOOL sysdir_entry = False;
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ pstring fname;
+ BOOL sysdir_entry = False;
- pstrcpy(fname,dname);
+ pstrcpy(fname,dname);
- /* Quick check for "." and ".." */
- if (fname[0] == '.') {
- if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if (attrs & aDIR) {
- sysdir_entry = True;
- } else {
- continue;
- }
+ /* Quick check for "." and ".." */
+ if (fname[0] == '.') {
+ if (!fname[1]
+ || (fname[1] == '.' && !fname[2])) {
+ if (attrs & aDIR) {
+ sysdir_entry = True;
+ } else {
+ continue;
}
}
+ }
- if (!is_visible_file(conn, directory, dname, &sbuf1, False))
- continue;
+ if (!is_visible_file(conn, directory, dname, &sbuf1,
+ False)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
- continue;
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
- if (sysdir_entry) {
- error = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- }
+ if (sysdir_entry) {
+ status = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
+ }
- error = NT_STATUS_ACCESS_DENIED;
- slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
- if (!vfs_object_exist(conn, fname, &sbuf1)) {
- error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
- continue;
- }
- error = can_rename(conn,fname,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(error)) {
- DEBUG(6,("rename %s refused\n", fname));
- continue;
- }
- pstrcpy(destname,newname);
-
- if (!resolve_wildcards(fname,destname)) {
- DEBUG(6,("resolve_wildcards %s %s failed\n",
- fname, destname));
- continue;
- }
+ status = NT_STATUS_ACCESS_DENIED;
+ slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
+ dname);
+ if (!vfs_object_exist(conn, fname, &sbuf1)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6, ("rename %s failed. Error %s\n",
+ fname, nt_errstr(status)));
+ continue;
+ }
+ status = can_rename(conn,fname,attrs,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused\n", fname));
+ continue;
+ }
+ pstrcpy(destname,newname);
+
+ if (!resolve_wildcards(fname,destname)) {
+ DEBUG(6, ("resolve_wildcards %s %s failed\n",
+ fname, destname));
+ continue;
+ }
- if (strcsequal(fname,destname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
- count++;
- error = NT_STATUS_OK;
- continue;
- }
+ if (strcsequal(fname,destname)) {
+ rename_open_files(conn, NULL, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: identical names "
+ "in wildcard rename %s - success\n",
+ fname));
+ count++;
+ status = NT_STATUS_OK;
+ continue;
+ }
- if (!replace_if_exists &&
- vfs_file_exist(conn,destname, NULL)) {
- DEBUG(6,("file_exist %s\n", destname));
- error = NT_STATUS_OBJECT_NAME_COLLISION;
- continue;
- }
+ if (!replace_if_exists
+ && vfs_file_exist(conn,destname, NULL)) {
+ DEBUG(6,("file_exist %s\n", destname));
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ continue;
+ }
- if (rename_path_prefix_equal(fname, destname)) {
- return NT_STATUS_SHARING_VIOLATION;
- }
+ if (rename_path_prefix_equal(fname, destname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+ sbuf1.st_ino, NULL, NULL);
- if (!SMB_VFS_RENAME(conn,fname,destname)) {
- rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
- count++;
- error = NT_STATUS_OK;
- }
- TALLOC_FREE(lck);
- DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ count++;
+ status = NT_STATUS_OK;
}
- CloseDir(dir_hnd);
+ TALLOC_FREE(lck);
+ DEBUG(3,("rename_internals: doing rename on %s -> "
+ "%s\n",fname,destname));
}
+ CloseDir(dir_hnd);
+ }
+#if 0
+ /* Don't think needed any more - JRA. */
if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
if (!rcdest && bad_path_dest) {
if (ms_has_wild(last_component_dest))
@@ -4661,13 +4498,13 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
}
+#endif
+
+ if (count == 0 && NT_STATUS_IS_OK(status)) {
+ status = map_nt_error_from_unix(errno);
}
- if (count == 0 && NT_STATUS_IS_OK(error)) {
- error = map_nt_error_from_unix(errno);
- }
-
- return error;
+ return status;
}
/****************************************************************************
@@ -4683,18 +4520,19 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
char *p;
uint32 attrs = SVAL(inbuf,smb_vwv0);
NTSTATUS status;
- BOOL path_contains_wcard = False;
+ BOOL path1_contains_wcard = False;
+ BOOL path2_contains_wcard = False;
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
p++;
- p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
@@ -4705,7 +4543,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
+ status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4715,11 +4553,6 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- /*
- * Win2k needs a changenotify request response before it will
- * update after a rename..
- */
- process_pending_change_notify_queue((time_t)0);
outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBmv);
@@ -4730,8 +4563,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
Copy a file as part of a reply_copy.
******************************************************************/
-BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
- int count,BOOL target_is_directory, int *err_ret)
+/*
+ * TODO: check error codes on all callers
+ */
+
+NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
+ int count, BOOL target_is_directory)
{
SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
@@ -4739,9 +4576,8 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
pstring dest;
uint32 dosattrs;
uint32 new_create_disposition;
+ NTSTATUS status;
- *err_ret = 0;
-
pstrcpy(dest,dest1);
if (target_is_directory) {
char *p = strrchr_m(src,'/');
@@ -4755,7 +4591,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
}
if (!vfs_file_exist(conn,src,&src_sbuf)) {
- return(False);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (!target_is_directory && count) {
@@ -4763,21 +4599,21 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
} else {
if (!map_open_params_to_ntcreate(dest1,0,ofun,
NULL, NULL, &new_create_disposition, NULL)) {
- return(False);
+ return NT_STATUS_INVALID_PARAMETER;
}
}
- fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
+ status = open_file_ntcreate(conn,src,&src_sbuf,
FILE_GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
INTERNAL_OPEN_ONLY,
- NULL);
+ NULL, &fsp1);
- if (!fsp1) {
- return(False);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
dosattrs = dos_mode(conn, src, &src_sbuf);
@@ -4785,18 +4621,18 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
ZERO_STRUCTP(&sbuf2);
}
- fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
+ status = open_file_ntcreate(conn,dest,&sbuf2,
FILE_GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
new_create_disposition,
0,
dosattrs,
INTERNAL_OPEN_ONLY,
- NULL);
+ NULL, &fsp2);
- if (!fsp2) {
+ if (!NT_STATUS_IS_OK(status)) {
close_file(fsp1,ERROR_CLOSE);
- return(False);
+ return status;
}
if ((ofun&3) == 1) {
@@ -4825,9 +4661,17 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
* Thus we don't look at the error return from the
* close of fsp1.
*/
- *err_ret = close_file(fsp2,NORMAL_CLOSE);
+ status = close_file(fsp2,NORMAL_CLOSE);
- return(ret == (SMB_OFF_T)src_sbuf.st_size);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (ret != (SMB_OFF_T)src_sbuf.st_size) {
+ return NT_STATUS_DISK_FULL;
+ }
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -4850,11 +4694,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
- BOOL bad_path1 = False;
- BOOL bad_path2 = False;
BOOL path_contains_wcard1 = False;
BOOL path_contains_wcard2 = False;
- BOOL rc = True;
SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
START_PROFILE(SMBcopy);
@@ -4885,8 +4726,17 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
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);
+ status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
target_is_directory = VALID_STAT_OF_DIR(sbuf2);
@@ -4926,21 +4776,22 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask, SNUM(conn)))
- mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+ mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
has_wild = path_contains_wcard1;
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- if (resolve_wildcards(directory,newname) &&
- copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
+ if (resolve_wildcards(directory,newname)
+ && NT_STATUS_IS_OK(status = copy_file(
+ directory,newname,conn,ofun,
+ count,target_is_directory)))
count++;
- if(!count && err) {
- errno = err;
+ if(!count && !NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
- return(UNIXERROR(ERRHRD,ERRgeneral));
+ return ERROR_NT(status);
}
if (!count) {
exists = vfs_file_exist(conn,directory,NULL);
@@ -4948,39 +4799,49 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
} else {
struct smb_Dir *dir_hnd = NULL;
const char *dname;
+ long offset = 0;
pstring destname;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- if (check_name(directory,conn))
- dir_hnd = OpenDir(conn, directory, mask, 0);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ dir_hnd = OpenDir(conn, directory, mask, 0);
+ if (dir_hnd == NULL) {
+ status = map_nt_error_from_unix(errno);
+ return ERROR_NT(status);
+ }
- if (dir_hnd) {
- long offset = 0;
- error = ERRbadfile;
+ error = ERRbadfile;
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- pstring fname;
- pstrcpy(fname,dname);
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ pstring fname;
+ pstrcpy(fname,dname);
- if (!is_visible_file(conn, directory, dname, &sbuf1, False))
- continue;
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive))
- continue;
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
- error = ERRnoaccess;
- slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- pstrcpy(destname,newname);
- if (resolve_wildcards(fname,destname) &&
- copy_file(fname,destname,conn,ofun,
- count,target_is_directory,&err))
- count++;
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
+ error = ERRnoaccess;
+ slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+ pstrcpy(destname,newname);
+ if (resolve_wildcards(fname,destname) &&
+ NT_STATUS_IS_OK(status = copy_file(
+ fname,destname,conn,ofun,
+ count,target_is_directory))) {
+ count++;
}
- CloseDir(dir_hnd);
+ DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
}
+ CloseDir(dir_hnd);
}
if (count == 0) {
@@ -4991,16 +4852,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return(UNIXERROR(ERRHRD,ERRgeneral));
}
- if (exists) {
- END_PROFILE(SMBcopy);
- return ERROR_DOS(ERRDOS,error);
- } else {
- if((errno == ENOENT) && (bad_path1 || bad_path2)) {
- set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
- }
- END_PROFILE(SMBcopy);
- return(UNIXERROR(ERRDOS,error));
- }
+ END_PROFILE(SMBcopy);
+ return ERROR_DOS(ERRDOS,error);
}
outsize = set_message(outbuf,1,0,True);
@@ -5018,7 +4871,6 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
{
int snum;
int outsize = 0;
- BOOL ok = False;
pstring newdir;
NTSTATUS status;
@@ -5038,17 +4890,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
- if (strlen(newdir) == 0) {
- ok = True;
- } else {
- ok = vfs_directory_exist(conn,newdir,NULL);
- if (ok)
- set_conn_connectpath(conn,newdir);
- }
-
- if (!ok) {
- END_PROFILE(pathworks_setdir);
- return ERROR_DOS(ERRDOS,ERRbadpath);
+ if (strlen(newdir) != 0) {
+ if (!vfs_directory_exist(conn,newdir,NULL)) {
+ END_PROFILE(pathworks_setdir);
+ return ERROR_DOS(ERRDOS,ERRbadpath);
+ }
+ set_conn_connectpath(conn,newdir);
}
outsize = set_message(outbuf,0,0,False);
@@ -5067,12 +4914,12 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
Get a lock pid, dealing with large count requests.
****************************************************************************/
-uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
+uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
{
if(!large_file_format)
- return SVAL(data,SMB_LPID_OFFSET(data_offset));
+ return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
else
- return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
+ return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
}
/****************************************************************************
@@ -5209,14 +5056,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
uint16 num_locks = SVAL(inbuf,smb_vwv7);
SMB_BIG_UINT count = 0, offset = 0;
- uint16 lock_pid;
+ uint32 lock_pid;
int32 lock_timeout = IVAL(inbuf,smb_vwv4);
int i;
char *data;
BOOL large_file_format =
(locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
BOOL err;
- BOOL my_lock_ctx = False;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
START_PROFILE(SMBlockingX);
@@ -5229,12 +5075,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don't really want to be
compatible! (tridge) */
- return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks);
- }
-
- if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- /* Need to make this like a cancel.... JRA. */
- return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
}
/* Check if this is an oplock break on a file
@@ -5348,7 +5189,9 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
/* Setup the timeout in seconds. */
- lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
+ if (!lp_blocking_locks(SNUM(conn))) {
+ lock_timeout = 0;
+ }
/* Now do any requested locks */
data += ((large_file_format ? 20 : 10)*num_ulocks);
@@ -5357,7 +5200,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
of smb_lkrng structs */
for(i = 0; i < (int)num_locks; i++) {
- enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
+ enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
+ READ_LOCK:WRITE_LOCK);
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
@@ -5375,50 +5219,101 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
(double)count, (unsigned int)lock_pid,
fsp->fsp_name, (int)lock_timeout ));
- status = do_lock_spin(fsp,
+ if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ if (lp_blocking_locks(SNUM(conn))) {
+
+ /* Schedule a message to ourselves to
+ remove the blocking lock record and
+ return the right error. */
+
+ if (!blocking_lock_cancel(fsp,
+ lock_pid,
+ offset,
+ count,
+ WINDOWS_LOCK,
+ locktype,
+ NT_STATUS_FILE_LOCK_CONFLICT)) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
+ }
+ }
+ /* Remove a matching pending lock. */
+ status = do_lock_cancel(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
+ } else {
+ BOOL blocking_lock = lock_timeout ? True : False;
+ BOOL defer_lock = False;
+ struct byte_range_lock *br_lck;
+
+ br_lck = do_lock(fsp,
lock_pid,
count,
offset,
lock_type,
WINDOWS_LOCK,
- &my_lock_ctx);
+ blocking_lock,
+ &status);
+
+ if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
+ /* Windows internal resolution for blocking locks seems
+ to be about 200ms... Don't wait for less than that. JRA. */
+ if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
+ lock_timeout = lp_lock_spin_time();
+ }
+ defer_lock = True;
+ }
- if (NT_STATUS_V(status)) {
- /*
- * Interesting fact found by IFSTEST /t
- * LockOverlappedTest... Even if it's our own lock
- * context, we need to wait here as there may be an
- * unlock on the way. So I removed a "&&
- * !my_lock_ctx" from the following if statement. JRA.
- */
- if ((lock_timeout != 0) &&
- lp_blocking_locks(SNUM(conn)) &&
- ERROR_WAS_LOCK_DENIED(status)) {
+ /* This heuristic seems to match W2K3 very well. If a
+ lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
+ it pretends we asked for a timeout of between 150 - 300 milliseconds as
+ far as I can tell. Replacement for do_lock_spin(). JRA. */
+
+ if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
+ NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
+ defer_lock = True;
+ lock_timeout = lp_lock_spin_time();
+ }
+
+ if (br_lck && defer_lock) {
/*
* A blocking lock was requested. Package up
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length,
- fsp,
- lock_timeout,
- i,
- lock_pid,
- lock_type,
- WINDOWS_LOCK,
- offset,
- count)) {
+ if(push_blocking_lock_request(br_lck,
+ inbuf, length,
+ fsp,
+ lock_timeout,
+ i,
+ lock_pid,
+ lock_type,
+ WINDOWS_LOCK,
+ offset,
+ count)) {
+ TALLOC_FREE(br_lck);
END_PROFILE(SMBlockingX);
return -1;
}
}
- break;
+
+ TALLOC_FREE(br_lck);
+ }
+
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(status);
}
}
/* If any of the above locks failed, then we must unlock
all of the previous locks (X/Open spec). */
- if (i != num_locks && num_locks != 0) {
+
+ if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
+ (i != num_locks) &&
+ (num_locks != 0)) {
/*
* Ensure we don't do a remove on the lock that just failed,
* as under POSIX rules, if we have a lock already there, we
@@ -5505,7 +5400,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
tcount = maxcount;
total_read = 0;
- if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadBmpx);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -5529,7 +5424,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_readbmpx: send_smb failed.");
+ exit_server_cleanly("reply_readbmpx: send_smb failed.");
total_read += nread;
startpos += nread;
@@ -5637,7 +5532,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
not an SMBwritebmpx - set this up now so we don't forget */
SCVAL(outbuf,smb_com,SMBwritec);
- if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
+ if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
END_PROFILE(SMBwriteBmpx);
return(ERROR_DOS(ERRDOS,ERRlock));
}
@@ -5691,7 +5586,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_writebmpx: send_smb failed.");
+ exit_server_cleanly("reply_writebmpx: send_smb failed.");
/* Now the secondary */
outsize = set_message(outbuf,1,0,True);
diff --git a/source/smbd/sec_ctx.c b/source/smbd/sec_ctx.c
index a30123bfa79..be00db9adb8 100644
--- a/source/smbd/sec_ctx.c
+++ b/source/smbd/sec_ctx.c
@@ -252,13 +252,30 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
ctx_p->ut.ngroups = ngroups;
SAFE_FREE(ctx_p->ut.groups);
- if (token && (token == ctx_p->token))
+ if (token && (token == ctx_p->token)) {
smb_panic("DUPLICATE_TOKEN");
+ }
TALLOC_FREE(ctx_p->token);
- ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups);
- ctx_p->token = dup_nt_token(NULL, token);
+ if (ngroups) {
+ ctx_p->ut.groups = (gid_t *)memdup(groups,
+ sizeof(gid_t) * ngroups);
+ if (!ctx_p->ut.groups) {
+ smb_panic("memdup failed");
+ }
+ } else {
+ ctx_p->ut.groups = NULL;
+ }
+
+ if (token) {
+ ctx_p->token = dup_nt_token(NULL, token);
+ if (!ctx_p->token) {
+ smb_panic("dup_nt_token failed");
+ }
+ } else {
+ ctx_p->token = NULL;
+ }
become_id(uid, gid);
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 2bfeae9f541..ab32d656d38 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -36,6 +36,7 @@ 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;
+static SIG_ATOMIC_T got_sig_cld;
#ifdef WITH_DFS
extern int dcelogin_atmost_once;
@@ -60,18 +61,51 @@ static void smbd_set_server_fd(int fd)
client_setfd(fd);
}
+struct event_context *smbd_event_context(void)
+{
+ static struct event_context *ctx;
+
+ if (!ctx && !(ctx = event_context_init(NULL))) {
+ smb_panic("Could not init smbd event context\n");
+ }
+ return ctx;
+}
+
+struct messaging_context *smbd_messaging_context(void)
+{
+ static struct messaging_context *ctx;
+
+ if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
+ smbd_event_context()))) {
+ smb_panic("Could not init smbd messaging context\n");
+ }
+ return ctx;
+}
+
/*******************************************************************
What to do when smb.conf is updated.
********************************************************************/
static void smb_conf_updated(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
reload_services(False);
}
+/*******************************************************************
+ Delete a statcache entry.
+ ********************************************************************/
+
+static void smb_stat_cache_delete(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
+{
+ const char *name = (const char *)buf;
+ DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name));
+ stat_cache_delete(name);
+}
+
/****************************************************************************
Terminate signal.
****************************************************************************/
@@ -93,6 +127,15 @@ static void sig_hup(int sig)
}
/****************************************************************************
+ Catch a sigcld
+****************************************************************************/
+static void sig_cld(int sig)
+{
+ got_sig_cld = 1;
+ sys_select_signal(SIGCLD);
+}
+
+/****************************************************************************
Send a SIGTERM to our process group.
*****************************************************************************/
@@ -107,7 +150,8 @@ static void killkids(void)
****************************************************************************/
static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
- void *UNUSED(buf), size_t UNUSED(len))
+ void *UNUSED(buf), size_t UNUSED(len),
+ void *private_data)
{
DEBUG(10, ("** sam sync message received, ignoring\n"));
}
@@ -118,7 +162,7 @@ static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
****************************************************************************/
static void msg_sam_repl(int msg_type, struct process_id pid,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
uint32 low_serial;
@@ -152,7 +196,7 @@ static BOOL open_sockets_inetd(void)
}
static void msg_exit_server(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
DEBUG(3, ("got a SHUTDOWN message\n"));
exit_server_cleanly(NULL);
@@ -160,7 +204,7 @@ static void msg_exit_server(int msg_type, struct process_id src,
#ifdef DEVELOPER
static void msg_inject_fault(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
int sig;
@@ -189,6 +233,54 @@ static void msg_inject_fault(int msg_type, struct process_id src,
}
#endif /* DEVELOPER */
+struct child_pid {
+ struct child_pid *prev, *next;
+ pid_t pid;
+};
+
+static struct child_pid *children;
+static int num_children;
+
+static void add_child_pid(pid_t pid)
+{
+ struct child_pid *child;
+
+ if (lp_max_smbd_processes() == 0) {
+ /* Don't bother with the child list if we don't care anyway */
+ return;
+ }
+
+ child = SMB_MALLOC_P(struct child_pid);
+ if (child == NULL) {
+ DEBUG(0, ("Could not add child struct -- malloc failed\n"));
+ return;
+ }
+ child->pid = pid;
+ DLIST_ADD(children, child);
+ num_children += 1;
+}
+
+static void remove_child_pid(pid_t pid)
+{
+ struct child_pid *child;
+
+ if (lp_max_smbd_processes() == 0) {
+ /* Don't bother with the child list if we don't care anyway */
+ return;
+ }
+
+ for (child = children; child != NULL; child = child->next) {
+ if (child->pid == pid) {
+ struct child_pid *tmp = child;
+ DLIST_REMOVE(children, child);
+ SAFE_FREE(tmp);
+ num_children -= 1;
+ return;
+ }
+ }
+
+ DEBUG(0, ("Could not find child %d -- ignoring\n", (int)pid));
+}
/****************************************************************************
Have we reached the process limit ?
@@ -201,27 +293,7 @@ static BOOL allowable_number_of_smbd_processes(void)
if (!max_processes)
return True;
- {
- TDB_CONTEXT *tdb = conn_tdb_ctx();
- int32 val;
- if (!tdb) {
- DEBUG(0,("allowable_number_of_smbd_processes: can't open connection tdb.\n" ));
- return False;
- }
-
- val = tdb_fetch_int32(tdb, "INFO/total_smbds");
- if (val == -1 && (tdb_error(tdb) != TDB_ERR_NOEXIST)) {
- DEBUG(0,("allowable_number_of_smbd_processes: can't fetch INFO/total_smbds. Error %s\n",
- tdb_errorstr(tdb) ));
- return False;
- }
- if (val > max_processes) {
- DEBUG(0,("allowable_number_of_smbd_processes: number of processes (%d) is over allowed limit (%d)\n",
- val, max_processes ));
- return False;
- }
- }
- return True;
+ return num_children < max_processes;
}
/****************************************************************************
@@ -255,7 +327,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
#endif
/* Stop zombies */
- CatchChild();
+ CatchSignal(SIGCLD, sig_cld);
FD_ZERO(&listen_set);
@@ -369,14 +441,16 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
/* Listen to messages */
- message_register(MSG_SMB_SAM_SYNC, msg_sam_sync);
- message_register(MSG_SMB_SAM_REPL, msg_sam_repl);
- message_register(MSG_SHUTDOWN, msg_exit_server);
- message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed);
- message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated);
+ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync, NULL);
+ message_register(MSG_SMB_SAM_REPL, msg_sam_repl, NULL);
+ message_register(MSG_SHUTDOWN, msg_exit_server, NULL);
+ message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed, NULL);
+ message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated, NULL);
+ message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete,
+ NULL);
#ifdef DEVELOPER
- message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault);
+ message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault, NULL);
#endif
/* now accept incoming connections - forking a new process
@@ -392,6 +466,15 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
/* Ensure we respond to PING and DEBUG messages from the main smbd. */
message_dispatch();
+ if (got_sig_cld) {
+ pid_t pid;
+ got_sig_cld = False;
+
+ while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
+ remove_child_pid(pid);
+ }
+ }
+
memcpy((char *)&lfds, (char *)&listen_set,
sizeof(listen_set));
@@ -421,6 +504,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
for( ; num > 0; num--) {
struct sockaddr addr;
socklen_t in_addrlen = sizeof(addr);
+ pid_t child = 0;
s = -1;
for(i = 0; i < num_sockets; i++) {
@@ -450,8 +534,14 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
if (smbd_server_fd() != -1 && interactive)
return True;
- if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && sys_fork()==0) {
+ if (allowable_number_of_smbd_processes() &&
+ smbd_server_fd() != -1 &&
+ ((child = sys_fork())==0)) {
/* Child code ... */
+
+ /* Stop zombies, the parent explicitly handles
+ * them, counting worker smbds. */
+ CatchChild();
/* close the listening socket(s) */
for(i = 0; i < num_sockets; i++)
@@ -467,7 +557,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
/* this is needed so that we get decent entries
in smbstatus for port 445 connects */
- set_remote_machine_name(get_peer_addr(smbd_server_fd()), False);
+ set_remote_machine_name(get_peer_addr(smbd_server_fd()),
+ False);
/* Reset the state of the random
* number generation system, so
@@ -475,7 +566,8 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
* numbers as each other */
set_need_random_reseed();
- /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
+ /* tdb needs special fork handling - remove
+ * CLEAR_IF_FIRST flags */
if (tdb_reopen_all(1) == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
smb_panic("tdb_reopen_all failed.");
@@ -496,6 +588,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
smbd_set_server_fd(-1);
+ if (child != 0) {
+ add_child_pid(child);
+ }
+
/* Force parent to check log size after
* spawning child. Fix from
* klausr@ITAP.Physik.Uni-Stuttgart.De. The
@@ -637,7 +733,6 @@ static void exit_server_common(enum server_exit_reason how,
yield_connection(NULL,"");
respond_to_all_remaining_local_messages();
- decrement_smbd_process_count();
#ifdef WITH_DFS
if (dcelogin_atmost_once) {
@@ -666,9 +761,7 @@ static void exit_server_common(enum server_exit_reason how,
}
DEBUGLEVEL = oldlevel;
-#if DUMP_CORE
dump_core();
-#endif
} else {
DEBUG(3,("Server exit (%s)\n",
@@ -729,7 +822,7 @@ static BOOL init_structs(void )
mkproto.h. Mixing $(builddir) and $(srcdir) source files in the current
prototype generation system is too complicated. */
-void build_options(BOOL screen);
+extern void build_options(BOOL screen);
int main(int argc,const char *argv[])
{
@@ -759,6 +852,8 @@ void build_options(BOOL screen);
load_case_tables();
+ TimeInit();
+
#ifdef HAVE_SET_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
#endif
@@ -912,18 +1007,12 @@ void build_options(BOOL screen);
if (!message_init())
exit(1);
- /* Initialize our global sam sid first -- quite a lot of the other
- * initialization routines further down depend on it.
- */
-
/* Initialise the password backed before the global_sam_sid
to ensure that we fetch from ldap before we make a domain sid up */
if(!initialize_password_db(False))
exit(1);
- /* Fail gracefully if we can't open secrets.tdb */
-
if (!secrets_init()) {
DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
exit(1);
@@ -991,8 +1080,12 @@ void build_options(BOOL screen);
init_modules();
- /* possibly reload the services file. */
- reload_services(True);
+ /* Possibly reload the services file. Only worth doing in
+ * daemon mode. In inetd mode, we know we only just loaded this.
+ */
+ if (is_daemon) {
+ reload_services(True);
+ }
if (!init_account_policy()) {
DEBUG(0,("Could not open account policy tdb.\n"));
@@ -1008,18 +1101,11 @@ void build_options(BOOL screen);
if (!init_oplocks())
exit(1);
- /* Setup change notify */
- if (!init_change_notify())
- exit(1);
-
/* Setup aio signal handler. */
initialize_async_io_handler();
- /* re-initialise the timezone */
- TimeInit();
-
/* register our message handlers */
- message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
+ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL);
smbd_process();
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 1cad6fb136a..b38a4c869c8 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -22,6 +22,31 @@
extern userdom_struct current_user_info;
+static BOOL canonicalize_path(connection_struct *conn, pstring path)
+{
+#ifdef REALPATH_TAKES_NULL
+ char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
+ if (!resolved_name) {
+ return False;
+ }
+ pstrcpy(path, resolved_name);
+ SAFE_FREE(resolved_name);
+ return True;
+#else
+#ifdef PATH_MAX
+ char resolved_name_buf[PATH_MAX+1];
+#else
+ pstring resolved_name_buf;
+#endif
+ char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
+ if (!resolved_name) {
+ return False;
+ }
+ pstrcpy(path, resolved_name);
+ return True;
+#endif /* REALPATH_TAKES_NULL */
+}
+
/****************************************************************************
Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
absolute path stating in / and not ending in /.
@@ -95,13 +120,22 @@ void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
if (!(*s & 0x80)) {
*d++ = *s++;
} else {
- switch(next_mb_char_size(s)) {
+ size_t siz;
+ /* Get the size of the next MB character. */
+ next_codepoint(s,&siz);
+ switch(siz) {
+ case 5:
+ *d++ = *s++;
+ /*fall through*/
case 4:
*d++ = *s++;
+ /*fall through*/
case 3:
*d++ = *s++;
+ /*fall through*/
case 2:
*d++ = *s++;
+ /*fall through*/
case 1:
*d++ = *s++;
break;
@@ -278,6 +312,13 @@ int find_service(fstring service)
if (iService < 0) {
}
+ /* Is it a usershare service ? */
+ if (iService < 0 && *lp_usershare_path()) {
+ /* Ensure the name is canonicalized. */
+ strlower_m(service);
+ iService = load_usershare_service(service);
+ }
+
/* just possibly it's a default service? */
if (iService < 0) {
char *pdefservice = lp_defaultservice();
@@ -290,6 +331,14 @@ int find_service(fstring service)
*/
pstring defservice;
pstrcpy(defservice, pdefservice);
+
+ /* Disallow anything except explicit share names. */
+ if (strequal(defservice,HOMES_NAME) ||
+ strequal(defservice, PRINTERS_NAME) ||
+ strequal(defservice, "IPC$")) {
+ goto fail;
+ }
+
iService = find_service(defservice);
if (iService >= 0) {
all_string_sub(service, "_","/",0);
@@ -298,13 +347,6 @@ int find_service(fstring service)
}
}
- /* Is it a usershare service ? */
- if (iService < 0 && *lp_usershare_path()) {
- /* Ensure the name is canonicalized. */
- strlower_m(service);
- iService = load_usershare_service(service);
- }
-
if (iService >= 0) {
if (!VALID_SNUM(iService)) {
DEBUG(0,("Invalid snum %d for %s\n",iService, service));
@@ -312,6 +354,8 @@ int find_service(fstring service)
}
}
+ fail:
+
if (iService < 0)
DEBUG(3,("find_service() failed to find service %s\n", service));
@@ -365,41 +409,29 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev)
return NT_STATUS_OK;
}
-static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest,
- uid_t *uid, gid_t *gid, fstring username,
- struct nt_user_token **token)
+static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username)
{
- TALLOC_CTX *mem_ctx;
+ int snum = conn->params->service;
char *fuser, *found_username;
NTSTATUS result;
- mem_ctx = talloc_new(NULL);
- if (mem_ctx == NULL) {
- DEBUG(0, ("talloc_new failed\n"));
+ if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
+ lp_servicename(snum)))) {
return NT_STATUS_NO_MEMORY;
}
- fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
- lp_servicename(snum));
- if (fuser == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
-
- result = create_token_from_username(mem_ctx, fuser, vuser_is_guest,
- uid, gid, &found_username,
- token);
+ result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
+ &conn->uid, &conn->gid, &found_username,
+ &conn->nt_user_token);
if (!NT_STATUS_IS_OK(result)) {
- goto done;
+ return result;
}
- talloc_steal(NULL, *token);
fstrcpy(username, found_username);
- result = NT_STATUS_OK;
- done:
- TALLOC_FREE(mem_ctx);
- return result;
+ TALLOC_FREE(fuser);
+ TALLOC_FREE(found_username);
+ return NT_STATUS_OK;
}
/*
@@ -417,7 +449,7 @@ static NTSTATUS find_forced_group(BOOL force_user,
NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
TALLOC_CTX *mem_ctx;
DOM_SID group_sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
char *groupname;
BOOL user_must_be_member = False;
gid_t gid;
@@ -532,12 +564,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
+ conn->params->service = snum;
conn->nt_user_token = NULL;
if (lp_guest_only(snum)) {
const char *guestname = lp_guestaccount();
NTSTATUS status2;
- char *found_username;
+ char *found_username = NULL;
+
guest = True;
pass = getpwnam_alloc(NULL, guestname);
if (!pass) {
@@ -547,11 +581,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*status = NT_STATUS_NO_SUCH_USER;
return NULL;
}
- status2 = create_token_from_username(NULL, pass->pw_name, True,
+ status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
&conn->uid, &conn->gid,
&found_username,
&conn->nt_user_token);
if (!NT_STATUS_IS_OK(status2)) {
+ TALLOC_FREE(pass);
conn_free(conn);
*status = status2;
return NULL;
@@ -559,6 +594,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
fstrcpy(user, found_username);
string_set(&conn->user,user);
conn->force_user = True;
+ TALLOC_FREE(found_username);
TALLOC_FREE(pass);
DEBUG(3,("Guest only user %s\n",user));
} else if (vuser) {
@@ -591,7 +627,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
guest = vuser->guest;
} else if (lp_security() == SEC_SHARE) {
NTSTATUS status2;
- char *found_username;
+ char *found_username = NULL;
+
/* add it as a possible user name if we
are in share mode security */
add_session_user(lp_servicename(snum));
@@ -604,7 +641,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
pass = Get_Pwnam(user);
- status2 = create_token_from_username(NULL, pass->pw_name, True,
+ status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
&conn->uid, &conn->gid,
&found_username,
&conn->nt_user_token);
@@ -615,6 +652,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
}
fstrcpy(user, found_username);
string_set(&conn->user,user);
+ TALLOC_FREE(found_username);
conn->force_user = True;
} else {
DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
@@ -629,7 +667,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
sizeof(conn->client_address)-1);
conn->num_files_open = 0;
conn->lastused = conn->lastused_count = time(NULL);
- conn->service = snum;
conn->used = True;
conn->printer = (strncmp(dev,"LPT",3) == 0);
conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
@@ -655,7 +692,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
string_set(&conn->dirpath,"");
string_set(&conn->user,user);
- conn->read_only = lp_readonly(conn->service);
+ conn->read_only = lp_readonly(SNUM(conn));
conn->admin_user = False;
/*
@@ -667,10 +704,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if (*lp_force_user(snum)) {
NTSTATUS status2;
- status2 = find_forced_user(snum,
- (vuser != NULL) && vuser->guest,
- &conn->uid, &conn->gid, user,
- &conn->nt_user_token);
+ status2 = find_forced_user(conn,
+ (vuser != NULL) && vuser->guest,
+ user);
if (!NT_STATUS_IS_OK(status2)) {
conn_free(conn);
*status = status2;
@@ -747,15 +783,24 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
sid_string_static(sid)));
continue;
}
- add_gid_to_array_unique(NULL, gid, &conn->groups,
- &conn->ngroups);
+ if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
+ &conn->ngroups)) {
+ DEBUG(0, ("add_gid_to_array_unique failed\n"));
+ conn_free(conn);
+ *status = NT_STATUS_NO_MEMORY;
+ return NULL;
+ }
}
}
{
pstring s;
pstrcpy(s,lp_pathname(snum));
- standard_sub_conn(conn,s,sizeof(s));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ s, sizeof(s));
set_conn_connectpath(conn,s);
DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
lp_servicename(snum)));
@@ -769,11 +814,16 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*/
{
- BOOL can_write = share_access_check(conn, snum, vuser,
+ NT_USER_TOKEN *token = conn->nt_user_token ?
+ conn->nt_user_token : vuser->nt_user_token;
+
+ BOOL can_write = share_access_check(token,
+ lp_servicename(snum),
FILE_WRITE_DATA);
if (!can_write) {
- if (!share_access_check(conn, snum, vuser,
+ if (!share_access_check(token,
+ lp_servicename(snum),
FILE_READ_DATA)) {
/* No access, read or write. */
DEBUG(0,("make_connection: connection to %s "
@@ -812,6 +862,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
set_conn_connectpath(conn,s);
}
+ if ((!conn->printer) && (!conn->ipc)) {
+ conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
+ smbd_messaging_context(),
+ smbd_event_context(),
+ conn);
+ }
+
/* ROOT Activities: */
/* check number of connections */
if (!claim_connection(conn,
@@ -830,7 +887,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if (*lp_rootpreexec(snum)) {
pstring cmd;
pstrcpy(cmd,lp_rootpreexec(snum));
- standard_sub_conn(conn,cmd,sizeof(cmd));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ cmd, sizeof(cmd));
DEBUG(5,("cmd=%s\n",cmd));
ret = smbrun(cmd,NULL);
if (ret != 0 && lp_rootpreexec_close(snum)) {
@@ -863,7 +924,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if (*lp_preexec(snum)) {
pstring cmd;
pstrcpy(cmd,lp_preexec(snum));
- standard_sub_conn(conn,cmd,sizeof(cmd));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ cmd, sizeof(cmd));
ret = smbrun(cmd,NULL);
if (ret != 0 && lp_preexec_close(snum)) {
DEBUG(1,("preexec gave %d - failing connection\n",
@@ -957,9 +1022,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
dbgtext( "(pid %d)\n", (int)sys_getpid() );
}
- /* Setup the minimum value for a change notify wait time (seconds). */
- set_change_notify_timeout(lp_change_notify_timeout(snum));
-
/* we've finished with the user stuff - go back to root */
change_to_root_user();
return(conn);
@@ -1162,7 +1224,11 @@ void close_cnum(connection_struct *conn, uint16 vuid)
change_to_user(conn, vuid)) {
pstring cmd;
pstrcpy(cmd,lp_postexec(SNUM(conn)));
- standard_sub_conn(conn,cmd,sizeof(cmd));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ cmd, sizeof(cmd));
smbrun(cmd,NULL);
change_to_root_user();
}
@@ -1172,7 +1238,11 @@ void close_cnum(connection_struct *conn, uint16 vuid)
if (*lp_rootpostexec(SNUM(conn))) {
pstring cmd;
pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
- standard_sub_conn(conn,cmd,sizeof(cmd));
+ standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ cmd, sizeof(cmd));
smbrun(cmd,NULL);
}
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 41f8fd0ed43..bcb840a3fe4 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -1,8 +1,10 @@
/*
Unix SMB/CIFS implementation.
session handling for utmp and PAM
- Copyright (C) tridge@samba.org 2001
- Copyright (C) abartlet@pcug.org.au 2001
+
+ Copyright (C) tridge@samba.org 2001
+ Copyright (C) abartlet@samba.org 2001
+ Copyright (C) Gerald (Jerry) Carter 2006
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,6 +31,9 @@
static TDB_CONTEXT *tdb;
+/********************************************************************
+********************************************************************/
+
BOOL session_init(void)
{
if (tdb)
@@ -44,7 +49,10 @@ BOOL session_init(void)
return True;
}
-/* called when a session is created */
+/********************************************************************
+ called when a session is created
+********************************************************************/
+
BOOL session_claim(user_struct *vuser)
{
int i = 0;
@@ -126,6 +134,7 @@ BOOL session_claim(user_struct *vuser)
sessionid.gid = vuser->gid;
fstrcpy(sessionid.remote_machine, get_remote_machine_name());
fstrcpy(sessionid.ip_addr, client_addr());
+ sessionid.connect_start = time(NULL);
client_ip = client_inaddr(&sa);
@@ -159,7 +168,10 @@ BOOL session_claim(user_struct *vuser)
return True;
}
-/* called when a session is destroyed */
+/********************************************************************
+ called when a session is destroyed
+********************************************************************/
+
void session_yield(user_struct *vuser)
{
TDB_DATA dbuf;
@@ -198,6 +210,9 @@ void session_yield(user_struct *vuser)
tdb_delete(tdb, key);
}
+/********************************************************************
+********************************************************************/
+
BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
void *state)
{
@@ -210,32 +225,40 @@ BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
return True;
}
+/********************************************************************
+********************************************************************/
+
struct session_list {
int count;
struct sessionid *sessions;
};
-static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf,
- void *state)
+static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
+ uint32 i;
struct session_list *sesslist = (struct session_list *) state;
const struct sessionid *current = (const struct sessionid *) dbuf.dptr;
- sesslist->count += 1;
- sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid,
- sesslist->count);
+ i = sesslist->count;
+
+ sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1);
if (!sesslist->sessions) {
sesslist->count = 0;
return -1;
}
- memcpy(&sesslist->sessions[sesslist->count - 1], current,
- sizeof(struct sessionid));
+ memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid));
+ sesslist->count++;
+
DEBUG(7,("gather_sessioninfo session from %s@%s\n",
current->username, current->remote_machine));
+
return 0;
}
+/********************************************************************
+********************************************************************/
+
int list_sessions(struct sessionid **session_list)
{
struct session_list sesslist;
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 8c8173ef374..7a5f8be47ff 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -23,6 +23,12 @@
#include "includes.h"
+extern struct auth_context *negprot_global_auth_context;
+extern BOOL global_encrypted_passwords_negotiated;
+extern BOOL global_spnego_negotiated;
+extern enum protocol_types Protocol;
+extern int max_send;
+
uint32 global_client_caps = 0;
/*
@@ -292,6 +298,21 @@ static int reply_spnego_kerberos(connection_struct *conn,
username_was_mapped = map_username( user );
pw = smb_getpwnam( mem_ctx, user, real_username, True );
+
+ if (pw) {
+ /* if a real user check pam account restrictions */
+ /* only really perfomed if "obey pam restriction" is true */
+ /* do this before an eventual mappign to guest occurs */
+ ret = smb_pam_accountcheck(pw->pw_name);
+ if ( !NT_STATUS_IS_OK(ret)) {
+ DEBUG(1, ("PAM account restriction prevents user login\n"));
+ data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
+ TALLOC_FREE(mem_ctx);
+ return ERROR_NT(nt_status_squash(ret));
+ }
+ }
+
if (!pw) {
/* this was originally the behavior of Samba 2.2, if a user
@@ -311,7 +332,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
}
@@ -335,7 +356,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return ERROR_NT(nt_status_squash(ret));
}
@@ -348,7 +369,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return ERROR_NT(nt_status_squash(ret));
}
@@ -415,7 +436,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
data_blob_free(&response);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return -1; /* already replied */
}
@@ -638,6 +659,200 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
}
/****************************************************************************
+ List to store partial SPNEGO auth fragments.
+****************************************************************************/
+
+static struct pending_auth_data *pd_list;
+
+/****************************************************************************
+ Delete an entry on the list.
+****************************************************************************/
+
+static void delete_partial_auth(struct pending_auth_data *pad)
+{
+ if (!pad) {
+ return;
+ }
+ DLIST_REMOVE(pd_list, pad);
+ data_blob_free(&pad->partial_data);
+ SAFE_FREE(pad);
+}
+
+/****************************************************************************
+ Search for a partial SPNEGO auth fragment matching an smbpid.
+****************************************************************************/
+
+static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
+{
+ struct pending_auth_data *pad;
+
+ for (pad = pd_list; pad; pad = pad->next) {
+ if (pad->smbpid == smbpid) {
+ break;
+ }
+ }
+ return pad;
+}
+
+/****************************************************************************
+ Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
+ else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
+****************************************************************************/
+
+static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
+{
+ struct pending_auth_data *pad = NULL;
+ ASN1_DATA data;
+ size_t needed_len = 0;
+
+ pad = get_pending_auth_data(smbpid);
+
+ /* Ensure we have some data. */
+ if (pblob->length == 0) {
+ /* Caller can cope. */
+ DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
+ delete_partial_auth(pad);
+ return NT_STATUS_OK;
+ }
+
+ /* Were we waiting for more data ? */
+ if (pad) {
+ DATA_BLOB tmp_blob;
+ size_t copy_len = MIN(65536, pblob->length);
+
+ /* Integer wrap paranoia.... */
+
+ if (pad->partial_data.length + copy_len < pad->partial_data.length ||
+ pad->partial_data.length + copy_len < copy_len) {
+
+ DEBUG(2,("check_spnego_blob_complete: integer wrap "
+ "pad->partial_data.length = %u, "
+ "copy_len = %u\n",
+ (unsigned int)pad->partial_data.length,
+ (unsigned int)copy_len ));
+
+ delete_partial_auth(pad);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ DEBUG(10,("check_spnego_blob_complete: "
+ "pad->partial_data.length = %u, "
+ "pad->needed_len = %u, "
+ "copy_len = %u, "
+ "pblob->length = %u,\n",
+ (unsigned int)pad->partial_data.length,
+ (unsigned int)pad->needed_len,
+ (unsigned int)copy_len,
+ (unsigned int)pblob->length ));
+
+ tmp_blob = data_blob(NULL,
+ pad->partial_data.length + copy_len);
+
+ /* Concatenate the two (up to copy_len) bytes. */
+ memcpy(tmp_blob.data,
+ pad->partial_data.data,
+ pad->partial_data.length);
+ memcpy(tmp_blob.data + pad->partial_data.length,
+ pblob->data,
+ copy_len);
+
+ /* Replace the partial data. */
+ data_blob_free(&pad->partial_data);
+ pad->partial_data = tmp_blob;
+ ZERO_STRUCT(tmp_blob);
+
+ /* Are we done ? */
+ if (pblob->length >= pad->needed_len) {
+ /* Yes, replace pblob. */
+ data_blob_free(pblob);
+ *pblob = pad->partial_data;
+ ZERO_STRUCT(pad->partial_data);
+ delete_partial_auth(pad);
+ return NT_STATUS_OK;
+ }
+
+ /* Still need more data. */
+ pad->needed_len -= copy_len;
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
+ (pblob->data[0] != ASN1_CONTEXT(1))) {
+ /* Not something we can determine the
+ * length of.
+ */
+ return NT_STATUS_OK;
+ }
+
+ /* This is a new SPNEGO sessionsetup - see if
+ * the data given in this blob is enough.
+ */
+
+ asn1_load(&data, *pblob);
+ asn1_start_tag(&data, pblob->data[0]);
+ if (data.has_error || data.nesting == NULL) {
+ asn1_free(&data);
+ /* Let caller catch. */
+ return NT_STATUS_OK;
+ }
+
+ /* Integer wrap paranoia.... */
+
+ if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
+ data.nesting->taglen + data.nesting->start < data.nesting->start) {
+
+ DEBUG(2,("check_spnego_blob_complete: integer wrap "
+ "data.nesting->taglen = %u, "
+ "data.nesting->start = %u\n",
+ (unsigned int)data.nesting->taglen,
+ (unsigned int)data.nesting->start ));
+
+ asn1_free(&data);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Total length of the needed asn1 is the tag length
+ * plus the current offset. */
+
+ needed_len = data.nesting->taglen + data.nesting->start;
+ asn1_free(&data);
+
+ DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
+ "pblob->length = %u\n",
+ (unsigned int)needed_len,
+ (unsigned int)pblob->length ));
+
+ if (needed_len <= pblob->length) {
+ /* Nothing to do - blob is complete. */
+ return NT_STATUS_OK;
+ }
+
+ /* Refuse the blob if it's bigger than 64k. */
+ if (needed_len > 65536) {
+ DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
+ (unsigned int)needed_len ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* We must store this blob until complete. */
+ pad = SMB_MALLOC(sizeof(struct pending_auth_data));
+ if (!pad) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ pad->needed_len = needed_len - pblob->length;
+ pad->partial_data = data_blob(pblob->data, pblob->length);
+ if (pad->partial_data.data == NULL) {
+ SAFE_FREE(pad);
+ return NT_STATUS_NO_MEMORY;
+ }
+ pad->smbpid = smbpid;
+ pad->vuid = vuid;
+ DLIST_ADD(pd_list, pad);
+
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+/****************************************************************************
Reply to a session setup command.
conn POINTER CAN BE NULL HERE !
****************************************************************************/
@@ -656,6 +871,8 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
enum remote_arch_types ra_type = get_remote_arch();
int vuid = SVAL(inbuf,smb_uid);
user_struct *vuser = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+ uint16 smbpid = SVAL(inbuf,smb_pid);
DEBUG(3,("Doing spnego session setup\n"));
@@ -694,16 +911,28 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
/* Windows 2003 doesn't set the native lanman string,
but does set primary domain which is a bug I think */
- if ( !strlen(native_lanman) )
+ if ( !strlen(native_lanman) ) {
ra_lanman_string( primary_domain );
- else
+ } else {
ra_lanman_string( native_lanman );
+ }
}
vuser = get_partial_auth_user_struct(vuid);
if (!vuser) {
+ struct pending_auth_data *pad = get_pending_auth_data(smbpid);
+ if (pad) {
+ DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
+ (unsigned int)pad->vuid ));
+ vuid = pad->vuid;
+ vuser = get_partial_auth_user_struct(vuid);
+ }
+ }
+
+ if (!vuser) {
vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
if (vuid == UID_FIELD_INVALID ) {
+ data_blob_free(&blob1);
return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
@@ -711,11 +940,27 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
}
if (!vuser) {
+ data_blob_free(&blob1);
return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
SSVAL(outbuf,smb_uid,vuid);
-
+
+ /* Large (greater than 4k) SPNEGO blobs are split into multiple
+ * sessionsetup requests as the Windows limit on the security blob
+ * field is 4k. Bug #4400. JRA.
+ */
+
+ status = check_spnego_blob_complete(smbpid, vuid, &blob1);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ /* Real error - kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ }
+ data_blob_free(&blob1);
+ return ERROR_NT(nt_status_squash(status));
+ }
+
if (blob1.data[0] == ASN1_APPLICATION(0)) {
/* its a negTokenTarg packet */
ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
@@ -734,25 +979,24 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
DATA_BLOB chal;
- NTSTATUS nt_status;
if (!vuser->auth_ntlmssp_state) {
- nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
- if (!NT_STATUS_IS_OK(nt_status)) {
+ status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
-
- return ERROR_NT(nt_status_squash(nt_status));
+ data_blob_free(&blob1);
+ return ERROR_NT(nt_status_squash(status));
}
}
- nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
+ status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
blob1, &chal);
data_blob_free(&blob1);
reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
&vuser->auth_ntlmssp_state,
- &chal, nt_status, False);
+ &chal, status, False);
data_blob_free(&chal);
return -1;
}
@@ -825,13 +1069,7 @@ 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;
@@ -1035,6 +1273,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
map_username(sub_user);
add_session_user(sub_user);
+ add_session_workgroup(domain);
/* Then force it to null for the benfit of the code below */
*user = 0;
}
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
index a8a54123318..adb9d169642 100644
--- a/source/smbd/share_access.c
+++ b/source/smbd/share_access.c
@@ -28,6 +28,8 @@
* + and & may be combined
*/
+extern userdom_struct current_user_info;
+
static BOOL do_group_checks(const char **name, const char **pattern)
{
if ((*name)[0] == '@') {
@@ -71,10 +73,11 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
{
const char *prefix;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (username != NULL) {
- name = talloc_sub_basic(mem_ctx, username, name);
+ name = talloc_sub_basic(mem_ctx, username,
+ current_user_info.domain, name);
}
if (sharename != NULL) {
name = talloc_string_sub(mem_ctx, name, "%S", sharename);
diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c
index 548d7c4a487..1a2b7a8237b 100644
--- a/source/smbd/statcache.c
+++ b/source/smbd/statcache.c
@@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
if (!lp_stat_cache())
return;
- if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) {
+ if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) {
reset_stat_cache();
}
@@ -285,18 +285,52 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
}
}
+/***************************************************************************
+ Tell all smbd's to delete an entry.
+**************************************************************************/
+
+void send_stat_cache_delete_message(const char *name)
+{
+#ifdef DEVELOPER
+ message_send_all(conn_tdb_ctx(),
+ MSG_SMB_STAT_CACHE_DELETE,
+ name,
+ strlen(name)+1,
+ True,
+ NULL);
+#endif
+}
+
+/***************************************************************************
+ Delete an entry.
+**************************************************************************/
+
+void stat_cache_delete(const char *name)
+{
+ char *lname = strdup_upper(name);
+
+ if (!lname) {
+ return;
+ }
+ DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n",
+ lname, name ));
+
+ tdb_delete_bystring(tdb_stat_cache, lname);
+ SAFE_FREE(lname);
+}
+
/***************************************************************
Compute a hash value based on a string key value.
The function returns the bucket index number for the hashed key.
JRA. Use a djb-algorithm hash for speed.
***************************************************************/
-u32 fast_string_hash(TDB_DATA *key)
+unsigned int fast_string_hash(TDB_DATA *key)
{
- u32 n = 0;
+ unsigned int n = 0;
const char *p;
for (p = key->dptr; *p != '\0'; p++) {
- n = ((n << 5) + n) ^ (u32)(*p);
+ n = ((n << 5) + n) ^ (unsigned int)(*p);
}
return n;
}
diff --git a/source/smbd/statvfs.c b/source/smbd/statvfs.c
index 8f981a63288..300b14a7c08 100644
--- a/source/smbd/statvfs.c
+++ b/source/smbd/statvfs.c
@@ -21,7 +21,7 @@
#include "includes.h"
-#if defined(LINUX)
+#if defined(LINUX) && defined(HAVE_FSID_INT)
static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
{
struct statvfs statvfs_buf;
@@ -51,7 +51,7 @@ static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
*/
int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf)
{
-#if defined(LINUX)
+#if defined(LINUX) && defined(HAVE_FSID_INT)
return linux_statvfs(path, statbuf);
#else
/* BB change this to return invalid level */
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 445570c6c45..584345a906a 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
SMB transaction2 handling
- Copyright (C) Jeremy Allison 1994-2003
+ Copyright (C) Jeremy Allison 1994-2007
Copyright (C) Stefan (metze) Metzmacher 2003
Copyright (C) Volker Lendecke 2005
Copyright (C) Steve French 2005
@@ -170,8 +170,8 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
return NULL;
}
- for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
- ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
+ for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
+ ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
if (!ea_namelist) {
return NULL;
@@ -197,7 +197,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
if (sizeret) {
for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
- struct ea_list *listp, *tmp;
+ struct ea_list *listp;
if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
continue;
@@ -218,7 +218,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
(unsigned int)*pea_total_len, dos_ea_name,
(unsigned int)listp->ea.value.length ));
}
- DLIST_ADD_END(ea_list_head, listp, tmp);
+ DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
}
/* Add on 4 for total length. */
if (*pea_total_len) {
@@ -396,7 +396,6 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
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);
@@ -418,7 +417,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
}
offset += (namelen + 1); /* Go past the name + terminating zero. */
- DLIST_ADD_END(ea_list_head, eal, tmp);
+ DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
}
@@ -460,7 +459,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
return NULL;
}
- eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
+ eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
if (!eal->ea.value.data) {
return NULL;
}
@@ -493,14 +492,13 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d
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);
+ DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
offset += bytes_used;
}
@@ -570,10 +568,11 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
int send_trans2_replies(char *outbuf,
int bufsize,
- char *params,
+ const char *params,
int paramsize,
- char *pdata,
- int datasize)
+ const char *pdata,
+ int datasize,
+ int max_data_bytes)
{
/* As we are using a protocol > LANMAN1 then the max_send
variable must have been set in the sessetupX call.
@@ -584,8 +583,8 @@ int send_trans2_replies(char *outbuf,
int data_to_send = datasize;
int params_to_send = paramsize;
int useable_space;
- char *pp = params;
- char *pd = pdata;
+ const char *pp = params;
+ const char *pd = pdata;
int params_sent_thistime, data_sent_thistime, total_sent_thistime;
int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
int data_alignment_offset = 0;
@@ -594,12 +593,24 @@ int send_trans2_replies(char *outbuf,
set_message(outbuf,10,0,True);
+ /* Modify the data_to_send and datasize and set the error if
+ we're trying to send more than max_data_bytes. We still send
+ the part of the packet(s) that fit. Strange, but needed
+ for OS/2. */
+
+ if (max_data_bytes > 0 && datasize > max_data_bytes) {
+ DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
+ max_data_bytes, datasize ));
+ datasize = data_to_send = max_data_bytes;
+ error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
+ }
+
/* If there genuinely are no parameters or data to send just send the empty packet */
if(params_to_send == 0 && data_to_send == 0) {
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans2_replies: send_smb failed.");
+ exit_server_cleanly("send_trans2_replies: send_smb failed.");
return 0;
}
@@ -694,7 +705,7 @@ int send_trans2_replies(char *outbuf,
/* Send the packet */
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans2_replies: send_smb failed.");
+ exit_server_cleanly("send_trans2_replies: send_smb failed.");
pp += params_sent_thistime;
pd += data_sent_thistime;
@@ -740,9 +751,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
SMB_INO_T inode = 0;
SMB_STRUCT_STAT sbuf;
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;
@@ -780,7 +789,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
return(ERROR_DOS(ERRSRV,ERRaccess));
}
- srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -791,13 +800,18 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
/* XXXX we need to handle passed times, sattr and flags */
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
- if (!check_name(fname,conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ if (open_ofun == 0) {
+ return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
}
if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
@@ -824,35 +838,30 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
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);
+ ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
+ total_data - 4);
if (!ea_list) {
- talloc_destroy(ctx);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
} else if (IVAL(pdata,0) != 4) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- fsp = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
create_options,
open_attr,
oplock_request,
- &smb_action);
+ &smb_action, &fsp);
- if (!fsp) {
- talloc_destroy(ctx);
+ if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return ERROR_NT(status);
}
size = get_file_size(sbuf);
@@ -860,7 +869,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
mtime = sbuf.st_mtime;
inode = sbuf.st_ino;
if (fattr & aDIR) {
- talloc_destroy(ctx);
close_file(fsp,ERROR_CLOSE);
return(ERROR_DOS(ERRDOS,ERRnoaccess));
}
@@ -889,9 +897,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
}
- if (total_data && smb_action == FILE_WAS_CREATED) {
+ if (ea_list && 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,ERROR_CLOSE);
return ERROR_NT(status);
@@ -899,14 +906,14 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
/* Realloc the size of parameters and data we will return */
- *pparams = SMB_REALLOC(*pparams, 30);
+ *pparams = (char *)SMB_REALLOC(*pparams, 30);
if(*pparams == NULL ) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
params = *pparams;
SSVAL(params,0,fsp->fnum);
- SSVAL(params,2,open_attr);
+ SSVAL(params,2,fattr);
srv_put_dos_date2(params,4, mtime);
SIVAL(params,8, (uint32)size);
SSVAL(params,12,deny_mode);
@@ -932,7 +939,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
/* Send the required number of replies */
- send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
return -1;
}
@@ -998,12 +1005,24 @@ static uint32 unix_filetype(mode_t mode)
Map wire perms onto standard UNIX permissions. Obey share restrictions.
****************************************************************************/
-static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
+enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
+
+static NTSTATUS unix_perms_from_wire( connection_struct *conn,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 perms,
+ enum perm_type ptype,
+ mode_t *ret_perms)
{
mode_t ret = 0;
- if (perms == SMB_MODE_NO_CHANGE)
- return pst->st_mode;
+ if (perms == SMB_MODE_NO_CHANGE) {
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ } else {
+ *ret_perms = psbuf->st_mode;
+ return NT_STATUS_OK;
+ }
+ }
ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
@@ -1024,18 +1043,34 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps
ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
#endif
- if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
+ switch (ptype) {
+ case PERM_NEW_FILE:
+ /* Apply mode mask */
+ ret &= lp_create_mask(SNUM(conn));
+ /* Add in force bits */
+ ret |= lp_force_create_mode(SNUM(conn));
+ break;
+ case PERM_NEW_DIR:
ret &= lp_dir_mask(SNUM(conn));
/* Add in force bits */
ret |= lp_force_dir_mode(SNUM(conn));
- } else {
+ break;
+ case PERM_EXISTING_FILE:
/* Apply mode mask */
- ret &= lp_create_mask(SNUM(conn));
+ ret &= lp_security_mask(SNUM(conn));
/* Add in force bits */
- ret |= lp_force_create_mode(SNUM(conn));
+ ret |= lp_force_security_mode(SNUM(conn));
+ break;
+ case PERM_EXISTING_DIR:
+ /* Apply mode mask */
+ ret &= lp_dir_security_mask(SNUM(conn));
+ /* Add in force bits */
+ ret |= lp_force_dir_security_mode(SNUM(conn));
+ break;
}
- return ret;
+ *ret_perms = ret;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -1043,7 +1078,7 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps
****************************************************************************/
static BOOL get_lanman2_dir_entry(connection_struct *conn,
- void *inbuf, void *outbuf,
+ void *inbuf, char *outbuf,
char *path_mask,uint32 dirtype,int info_level,
int requires_resume_key,
BOOL dont_descend,char **ppdata,
@@ -1064,18 +1099,23 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SMB_OFF_T file_size = 0;
SMB_BIG_UINT allocation_size = 0;
uint32 len;
- time_t mdate=0, adate=0, cdate=0;
+ struct timespec mdate_ts, adate_ts, create_date_ts;
+ time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
char *nameptr;
char *last_entry_ptr;
BOOL was_8_3;
uint32 nt_extmode; /* Used for NT connections instead of mode */
BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
- BOOL check_mangled_names = lp_manglednames(SNUM(conn));
+ BOOL check_mangled_names = lp_manglednames(conn->params);
*fname = 0;
*out_of_space = False;
*got_exact_match = False;
+ ZERO_STRUCT(mdate_ts);
+ ZERO_STRUCT(adate_ts);
+ ZERO_STRUCT(create_date_ts);
+
if (!conn->dirptr)
return(False);
@@ -1117,7 +1157,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
got_match = mask_match(fname, mask, conn->case_sensitive);
- if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
+ if(!got_match && check_mangled_names &&
+ !mangle_is_8_3(fname, False, conn->params)) {
/*
* It turns out that NT matches wildcards against
@@ -1128,7 +1169,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
pstring newname;
pstrcpy( newname, fname);
- mangle_map( newname, True, False, SNUM(conn));
+ mangle_map( newname, True, False, conn->params);
if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
got_match = mask_match(newname, mask, conn->case_sensitive);
}
@@ -1183,17 +1224,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
if (!(mode & aDIR))
file_size = get_file_size(sbuf);
allocation_size = get_allocation_size(conn,NULL,&sbuf);
- mdate = sbuf.st_mtime;
- adate = sbuf.st_atime;
- cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+
+ mdate_ts = get_mtimespec(&sbuf);
+ adate_ts = get_atimespec(&sbuf);
+ create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
if (lp_dos_filetime_resolution(SNUM(conn))) {
- cdate &= ~1;
- mdate &= ~1;
- adate &= ~1;
+ dos_filetime_timespec(&create_date_ts);
+ dos_filetime_timespec(&mdate_ts);
+ dos_filetime_timespec(&adate_ts);
}
-
+ create_date = convert_timespec_to_time_t(create_date_ts);
+ mdate = convert_timespec_to_time_t(mdate_ts);
+ adate = convert_timespec_to_time_t(adate_ts);
+
DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
found = True;
@@ -1202,7 +1247,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
}
}
- mangle_map(fname,False,True,SNUM(conn));
+ mangle_map(fname,False,True,conn->params);
p = pdata;
last_entry_ptr = p;
@@ -1216,7 +1261,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SIVAL(p,0,reskey);
p += 4;
}
- srv_put_dos_date2(p,0,cdate);
+ srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
SIVAL(p,12,(uint32)file_size);
@@ -1248,7 +1293,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SIVAL(p,0,reskey);
p += 4;
}
- srv_put_dos_date2(p,0,cdate);
+ srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
SIVAL(p,12,(uint32)file_size);
@@ -1292,7 +1337,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SIVAL(p,0,reskey);
p += 4;
}
- srv_put_dos_date2(p,0,cdate);
+ srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
SIVAL(p,12,(uint32)file_size);
@@ -1338,13 +1383,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
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, SNUM(conn));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
p += 4;
SIVAL(p,0,reskey); p += 4;
- put_long_date(p,cdate); p += 8;
- put_long_date(p,adate); p += 8;
- put_long_date(p,mdate); p += 8;
- put_long_date(p,mdate); p += 8;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
SOFF_T(p,0,file_size); p += 8;
SOFF_T(p,0,allocation_size); p += 8;
SIVAL(p,0,nt_extmode); p += 4;
@@ -1361,7 +1406,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
if (!was_8_3 && check_mangled_names) {
pstring mangled_name;
pstrcpy(mangled_name, fname);
- mangle_map(mangled_name,True,True,SNUM(conn));
+ mangle_map(mangled_name,True,True,
+ conn->params);
mangled_name[12] = 0;
len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
if (len < 24) {
@@ -1386,10 +1432,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
p += 4;
SIVAL(p,0,reskey); p += 4;
- put_long_date(p,cdate); p += 8;
- put_long_date(p,adate); p += 8;
- put_long_date(p,mdate); p += 8;
- put_long_date(p,mdate); p += 8;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
SOFF_T(p,0,file_size); p += 8;
SOFF_T(p,0,allocation_size); p += 8;
SIVAL(p,0,nt_extmode); p += 4;
@@ -1407,10 +1453,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
p += 4;
SIVAL(p,0,reskey); p += 4;
- put_long_date(p,cdate); p += 8;
- put_long_date(p,adate); p += 8;
- put_long_date(p,mdate); p += 8;
- put_long_date(p,mdate); p += 8;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
SOFF_T(p,0,file_size); p += 8;
SOFF_T(p,0,allocation_size); p += 8;
SIVAL(p,0,nt_extmode); p += 4;
@@ -1452,10 +1498,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
p += 4;
SIVAL(p,0,reskey); p += 4;
- put_long_date(p,cdate); p += 8;
- put_long_date(p,adate); p += 8;
- put_long_date(p,mdate); p += 8;
- put_long_date(p,mdate); p += 8;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
SOFF_T(p,0,file_size); p += 8;
SOFF_T(p,0,allocation_size); p += 8;
SIVAL(p,0,nt_extmode); p += 4;
@@ -1480,13 +1526,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
- was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
p += 4;
SIVAL(p,0,reskey); p += 4;
- put_long_date(p,cdate); p += 8;
- put_long_date(p,adate); p += 8;
- put_long_date(p,mdate); p += 8;
- put_long_date(p,mdate); p += 8;
+ put_long_date_timespec(p,create_date_ts); p += 8;
+ put_long_date_timespec(p,adate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
+ put_long_date_timespec(p,mdate_ts); p += 8;
SOFF_T(p,0,file_size); p += 8;
SOFF_T(p,0,allocation_size); p += 8;
SIVAL(p,0,nt_extmode); p += 4;
@@ -1503,7 +1549,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
if (!was_8_3 && check_mangled_names) {
pstring mangled_name;
pstrcpy(mangled_name, fname);
- mangle_map(mangled_name,True,True,SNUM(conn));
+ mangle_map(mangled_name,True,True,
+ conn->params);
mangled_name[12] = 0;
len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
SSVAL(p, 0, len);
@@ -1542,9 +1589,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
p+= 8;
- put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
- put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
- put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
+ put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
+ put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
+ put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
p+= 24;
SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
@@ -1625,13 +1672,13 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
requested. */
char *params = *pparams;
char *pdata = *ppdata;
- uint32 dirtype = SVAL(params,0);
- int maxentries = SVAL(params,2);
- uint16 findfirst_flags = SVAL(params,4);
- BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
- BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
- BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
- int info_level = SVAL(params,6);
+ uint32 dirtype;
+ int maxentries;
+ uint16 findfirst_flags;
+ BOOL close_after_first;
+ BOOL close_if_end;
+ BOOL requires_resume_key;
+ int info_level;
pstring directory;
pstring mask;
char *p;
@@ -1643,17 +1690,24 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
BOOL dont_descend = False;
BOOL out_of_space = False;
int space_remaining;
- BOOL bad_path = False;
BOOL mask_contains_wcard = 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) {
+ if (total_params < 13) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
+ dirtype = SVAL(params,0);
+ maxentries = SVAL(params,2);
+ findfirst_flags = SVAL(params,4);
+ close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
+ close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+ requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+ info_level = SVAL(params,6);
+
*directory = *mask = 0;
DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
@@ -1686,19 +1740,20 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+ srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ERROR_NT(ntstatus);
}
- if(!check_name(directory,conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ ntstatus = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ERROR_NT(ntstatus);
}
p = strrchr_m(directory,'/');
@@ -1739,7 +1794,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
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) {
@@ -1748,7 +1803,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
}
- *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ *ppdata = (char *)SMB_REALLOC(
+ *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if(*ppdata == NULL ) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -1756,7 +1812,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
pdata = *ppdata;
/* Realloc the params space */
- *pparams = SMB_REALLOC(*pparams, 10);
+ *pparams = (char *)SMB_REALLOC(*pparams, 10);
if (*pparams == NULL) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -1766,13 +1822,23 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
/* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
- dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
- if (dptr_num < 0) {
+ ntstatus = dptr_create(conn,
+ directory,
+ False,
+ True,
+ SVAL(inbuf,smb_pid),
+ mask,
+ mask_contains_wcard,
+ dirtype,
+ &conn->dirptr);
+
+ if (!NT_STATUS_IS_OK(ntstatus)) {
talloc_destroy(ea_ctx);
- return(UNIXERROR(ERRDOS,ERRbadfile));
+ return ERROR_NT(ntstatus);
}
- DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
+ dptr_num = dptr_dnum(conn->dirptr);
+ DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
@@ -1854,7 +1920,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,6,0); /* Never an EA error */
SSVAL(params,8,last_entry_off);
- send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
+ send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -1871,8 +1937,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
* (see PR#13758). JRA.
*/
- if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
- mangle_map(mask, True, True, SNUM(conn));
+ if(!mangle_is_8_3_wildcards( mask, False, conn->params))
+ mangle_map(mask, True, True, conn->params);
return(-1);
}
@@ -1892,15 +1958,15 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
requested. */
char *params = *pparams;
char *pdata = *ppdata;
- int dptr_num = SVAL(params,0);
- int maxentries = SVAL(params,2);
- uint16 info_level = SVAL(params,4);
- uint32 resume_key = IVAL(params,6);
- uint16 findnext_flags = SVAL(params,10);
- BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
- BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
- BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
- BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
+ int dptr_num;
+ int maxentries;
+ uint16 info_level;
+ uint32 resume_key;
+ uint16 findnext_flags;
+ BOOL close_after_request;
+ BOOL close_if_end;
+ BOOL requires_resume_key;
+ BOOL continue_bit;
BOOL mask_contains_wcard = False;
pstring resume_name;
pstring mask;
@@ -1917,13 +1983,23 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
- if (total_params < 12) {
+ if (total_params < 13) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
+ dptr_num = SVAL(params,0);
+ maxentries = SVAL(params,2);
+ info_level = SVAL(params,4);
+ resume_key = IVAL(params,6);
+ findnext_flags = SVAL(params,10);
+ close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
+ close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+ requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+ continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
+
*mask = *directory = *resume_name = 0;
- srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+ srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
complain (it thinks we're asking for the directory above the shared
@@ -1999,7 +2075,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
}
- *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ *ppdata = (char *)SMB_REALLOC(
+ *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if(*ppdata == NULL) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -2008,7 +2085,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
pdata = *ppdata;
/* Realloc the params space */
- *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
+ *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
if(*pparams == NULL ) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -2068,8 +2145,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
* could be mangled. Ensure we check the unmangled name.
*/
- if (mangle_is_mangled(resume_name, SNUM(conn))) {
- mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
+ if (mangle_is_mangled(resume_name, conn->params)) {
+ mangle_check_cache(resume_name, sizeof(resume_name)-1,
+ conn->params);
}
/*
@@ -2134,7 +2212,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,4,0); /* Never an EA error */
SSVAL(params,6,last_entry_off);
- send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
+ send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -2156,7 +2234,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
{
char *pdata = *ppdata;
char *params = *pparams;
- uint16 info_level = SVAL(params,0);
+ uint16 info_level;
int data_len, len;
SMB_STRUCT_STAT st;
char *vname = volume_label(SNUM(conn));
@@ -2164,6 +2242,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
char *fstype = lp_fstype(SNUM(conn));
int quota_flag = 0;
+ if (total_params < 2) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
+ info_level = SVAL(params,0);
+
DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
if(SMB_VFS_STAT(conn,".",&st)!=0) {
@@ -2171,7 +2255,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
return ERROR_DOS(ERRSRV,ERRinvdevice);
}
- *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ *ppdata = (char *)SMB_REALLOC(
+ *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if (*ppdata == NULL ) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -2441,17 +2526,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
/* We have POSIX ACLs, pathname and locking capability. */
-#if defined(DEVELOPER) /* Not quite finished yet... */
- SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
- CIFS_UNIX_POSIX_ACLS_CAP|
- CIFS_UNIX_POSIX_PATHNAMES_CAP|
- CIFS_UNIX_FCNTL_LOCKS_CAP)));
-#else
SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
CIFS_UNIX_POSIX_ACLS_CAP|
CIFS_UNIX_POSIX_PATHNAMES_CAP|
- 0)));
-#endif
+ CIFS_UNIX_FCNTL_LOCKS_CAP|
+ CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
break;
case SMB_QUERY_POSIX_FS_INFO:
@@ -2503,7 +2582,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
- send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
+ send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
@@ -2567,11 +2646,16 @@ cap_low = 0x%x, cap_high = 0x%x\n",
lp_set_posix_pathnames();
mangle_change_to_posix();
}
-#if defined(DEVELOPER)
- if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
- lp_set_posix_cifsx_locktype(POSIX_LOCK);
+
+ if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
+ !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
+ /* Client that knows how to do posix locks,
+ * but not posix open/mkdir operations. Set a
+ * default type for read/write checks. */
+
+ lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
+
}
-#endif
break;
}
case SMB_FS_QUOTA_INFORMATION:
@@ -2663,25 +2747,6 @@ cap_low = 0x%x, cap_high = 0x%x\n",
return outsize;
}
-/****************************************************************************
- Utility function to set bad path error.
-****************************************************************************/
-
-int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
-{
- DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
- err, (int)bad_path ));
-
- if(err == ENOENT) {
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- } else {
- return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
- }
- }
- return UNIXERROR(def_class,def_code);
-}
-
#if defined(HAVE_POSIX_ACLS)
/****************************************************************************
Utility function to count the number of entries in a POSIX acl.
@@ -2800,6 +2865,62 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
#endif
/****************************************************************************
+ Store the FILE_UNIX_BASIC info.
+****************************************************************************/
+
+static char *store_file_unix_basic(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ SMB_STRUCT_STAT *psbuf)
+{
+ DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
+ DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
+
+ SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
+ pdata += 8;
+
+ SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
+ pdata += 8;
+
+ put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Creation Time 64 Bit */
+ put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
+ put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
+ pdata += 24;
+
+ SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
+ pdata += 4;
+
+ SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
+ pdata += 8;
+
+ SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ return pdata;
+}
+
+/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
file name or file id).
****************************************************************************/
@@ -2824,17 +2945,15 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
char *base_name;
char *p;
SMB_OFF_T pos = 0;
- BOOL bad_path = False;
BOOL delete_pending = False;
int len;
- time_t c_time;
+ time_t create_time, mtime, atime;
+ struct timespec create_time_ts, mtime_ts, atime_ts;
files_struct *fsp = NULL;
TALLOC_CTX *data_ctx = NULL;
struct ea_list *ea_list = NULL;
uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
-#if defined(DEVELOPER)
char *lock_data = NULL;
-#endif
if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -2872,11 +2991,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -2899,7 +3018,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
NTSTATUS status = NT_STATUS_OK;
/* qpathinfo */
- if (total_params < 6) {
+ if (total_params < 7) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -2907,31 +3026,32 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
- srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
- if (!check_name(fname,conn)) {
- DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
+ return ERROR_NT(status);
}
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
@@ -3006,7 +3126,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
break;
}
-#if defined(DEVELOPER)
+
case SMB_QUERY_POSIX_LOCK:
{
if (fsp == NULL || fsp->fh->fd == -1) {
@@ -3022,18 +3142,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
/* Copy the lock range data. */
- lock_data = talloc_memdup(data_ctx, pdata, total_data);
+ lock_data = (char *)talloc_memdup(
+ data_ctx, pdata, total_data);
if (!lock_data) {
talloc_destroy(data_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
}
-#endif
default:
break;
}
- *pparams = SMB_REALLOC(*pparams,2);
+ *pparams = (char *)SMB_REALLOC(*pparams,2);
if (*pparams == NULL) {
talloc_destroy(data_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -3041,28 +3161,32 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
params = *pparams;
SSVAL(params,0,0);
data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
- *ppdata = SMB_REALLOC(*ppdata, data_size);
+ *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
if (*ppdata == NULL ) {
talloc_destroy(data_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
pdata = *ppdata;
- c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ mtime_ts = get_mtimespec(&sbuf);
+ atime_ts = get_atimespec(&sbuf);
allocation_size = get_allocation_size(conn,fsp,&sbuf);
if (fsp) {
if (fsp->pending_modtime) {
/* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp->pending_modtime;
+ mtime_ts.tv_sec = fsp->pending_modtime;
+ mtime_ts.tv_nsec = 0;
}
} else {
/* Do we have this path open ? */
files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
if (fsp1 && fsp1->pending_modtime) {
/* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp1->pending_modtime;
+ mtime_ts.tv_sec = fsp1->pending_modtime;
+ mtime_ts.tv_nsec = 0;
}
if (fsp1 && fsp1->initial_allocation_size) {
allocation_size = get_allocation_size(conn, fsp1, &sbuf);
@@ -3070,12 +3194,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
if (lp_dos_filetime_resolution(SNUM(conn))) {
- c_time &= ~1;
- sbuf.st_atime &= ~1;
- sbuf.st_ctime &= ~1;
- sbuf.st_mtime &= ~1;
+ dos_filetime_timespec(&create_time_ts);
+ dos_filetime_timespec(&mtime_ts);
+ dos_filetime_timespec(&atime_ts);
}
+ create_time = convert_timespec_to_time_t(create_time_ts);
+ mtime = convert_timespec_to_time_t(mtime_ts);
+ atime = convert_timespec_to_time_t(atime_ts);
+
/* NT expects the name to be in an exact form of the *full*
filename. See the trans2 torture test */
if (strequal(base_name,".")) {
@@ -3089,9 +3216,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_INFO_STANDARD:
DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
data_size = 22;
- srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
- srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
- srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
+ srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
+ srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
+ srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
SIVAL(pdata,l1_cbFile,(uint32)file_size);
SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
SSVAL(pdata,l1_attrFile,mode);
@@ -3102,9 +3229,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
data_size = 26;
- srv_put_dos_date2(pdata,0,c_time);
- srv_put_dos_date2(pdata,4,sbuf.st_atime);
- srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
+ srv_put_dos_date2(pdata,0,create_time);
+ srv_put_dos_date2(pdata,4,atime);
+ srv_put_dos_date2(pdata,8,mtime); /* write time */
SIVAL(pdata,12,(uint32)file_size);
SIVAL(pdata,16,(uint32)allocation_size);
SSVAL(pdata,20,mode);
@@ -3180,20 +3307,17 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
data_size = 40;
SIVAL(pdata,36,0);
}
- put_long_date(pdata,c_time);
- put_long_date(pdata+8,sbuf.st_atime);
- put_long_date(pdata+16,sbuf.st_mtime); /* write time */
- put_long_date(pdata+24,sbuf.st_mtime); /* change time */
+ put_long_date_timespec(pdata,create_time_ts);
+ put_long_date_timespec(pdata+8,atime_ts);
+ put_long_date_timespec(pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(pdata+24,mtime_ts); /* change time */
SIVAL(pdata,32,mode);
DEBUG(5,("SMB_QFBI - "));
- {
- time_t create_time = c_time;
- DEBUG(5,("create: %s ", ctime(&create_time)));
- }
- DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
- DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
- DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
+ DEBUG(5,("create: %s ", ctime(&create_time)));
+ DEBUG(5,("access: %s ", ctime(&atime)));
+ DEBUG(5,("write: %s ", ctime(&mtime)));
+ DEBUG(5,("change: %s ", ctime(&mtime)));
DEBUG(5,("mode: %x\n", mode));
break;
@@ -3229,8 +3353,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
pstrcpy(short_name,base_name);
/* Mangle if not already 8.3 */
- if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
- mangle_map(short_name,True,True,SNUM(conn));
+ if(!mangle_is_8_3(short_name, True, conn->params)) {
+ mangle_map(short_name,True,True,conn->params);
}
len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
data_size = 4 + len;
@@ -3267,10 +3391,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
{
unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
- put_long_date(pdata,c_time);
- put_long_date(pdata+8,sbuf.st_atime);
- put_long_date(pdata+16,sbuf.st_mtime); /* write time */
- put_long_date(pdata+24,sbuf.st_mtime); /* change time */
+ put_long_date_timespec(pdata,create_time_ts);
+ put_long_date_timespec(pdata+8,atime_ts);
+ put_long_date_timespec(pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(pdata+24,mtime_ts); /* change time */
SIVAL(pdata,32,mode);
SIVAL(pdata,36,0); /* padding. */
pdata += 40;
@@ -3377,10 +3501,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_FILE_NETWORK_OPEN_INFORMATION:
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
- put_long_date(pdata,c_time);
- put_long_date(pdata+8,sbuf.st_atime);
- put_long_date(pdata+16,sbuf.st_mtime); /* write time */
- put_long_date(pdata+24,sbuf.st_mtime); /* change time */
+ put_long_date_timespec(pdata,create_time_ts);
+ put_long_date_timespec(pdata+8,atime_ts);
+ put_long_date_timespec(pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(pdata+24,mtime_ts); /* change time */
SIVAL(pdata,32,allocation_size);
SOFF_T(pdata,40,file_size);
SIVAL(pdata,48,mode);
@@ -3401,54 +3525,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_QUERY_FILE_UNIX_BASIC:
- DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
- DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
-
- SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
- pdata += 8;
-
- SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
- pdata += 8;
-
- put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
- put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
- put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
- pdata += 24;
-
- SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
- SIVAL(pdata,4,0);
- pdata += 8;
-
- SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
- SIVAL(pdata,4,0);
- pdata += 8;
-
- SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
- pdata += 4;
-
- SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
- SIVAL(pdata,4,0);
- pdata += 8;
-
- SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
- SIVAL(pdata,4,0);
- pdata += 8;
-
- SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
- pdata += 8;
-
- SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
- SIVAL(pdata,4,0);
- pdata += 8;
-
- SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
- SIVAL(pdata,4,0);
- pdata += 8;
+ pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
data_size = PTR_DIFF(pdata,(*ppdata));
{
int i;
- DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
for (i=0; i<100; i++)
DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
@@ -3559,13 +3641,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
#endif
-#if defined(DEVELOPER)
case SMB_QUERY_POSIX_LOCK:
{
NTSTATUS status = NT_STATUS_INVALID_LEVEL;
SMB_BIG_UINT count;
SMB_BIG_UINT offset;
- uint16 lock_pid;
+ uint32 lock_pid;
enum brl_type lock_type;
if (total_data != POSIX_LOCK_DATA_SIZE) {
@@ -3586,7 +3667,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
+ lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
#if defined(HAVE_LONGLONG)
offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
@@ -3632,13 +3713,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
break;
}
-#endif
default:
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
+ send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
return(-1);
}
@@ -3648,10 +3728,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
code.
****************************************************************************/
-NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
+NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
{
- BOOL bad_path_oldname = False;
- BOOL bad_path_newname = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
pstring last_component_newname;
@@ -3660,21 +3738,9 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- /* No wildcards. */
- if (ms_has_wild(newname) || ms_has_wild(oldname)) {
- return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- }
-
- unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
- if (bad_path_oldname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_oldname[0] == '.') {
- if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* source must already exist. */
@@ -3682,20 +3748,14 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (!check_name(oldname,conn)) {
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_ACCESS_DENIED;
}
- unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
- if (bad_path_newname) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- /* Quick check for "." and ".." */
- if (last_component_newname[0] == '.') {
- if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Disallow if newname already exists. */
@@ -3703,7 +3763,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (!check_name(newname,conn)) {
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_ACCESS_DENIED;
}
@@ -3713,8 +3774,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
}
/* Ensure this is within the share. */
- if (!reduce_name(conn, oldname) != 0)
- return NT_STATUS_ACCESS_DENIED;
+ status = reduce_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
@@ -3728,1016 +3791,1745 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
}
/****************************************************************************
- Reply to a TRANS2_SETFILEINFO (set file info by fileid).
+ Deal with setting the time from any of the setfilepathinfo functions.
****************************************************************************/
-static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
- unsigned int tran_call,
- char **pparams, int total_params, char **ppdata, int total_data,
- unsigned int max_data_bytes)
+static NTSTATUS smb_set_file_time(connection_struct *conn,
+ files_struct *fsp,
+ const char *fname,
+ const SMB_STRUCT_STAT *psbuf,
+ struct utimbuf tvs)
{
- char *params = *pparams;
- char *pdata = *ppdata;
- uint16 info_level;
- int dosmode=0;
- SMB_OFF_T size=0;
- struct utimbuf tvs;
- SMB_STRUCT_STAT sbuf;
- pstring fname;
- int fd = -1;
- BOOL bad_path = False;
- files_struct *fsp = NULL;
- uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
- gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
- mode_t unixmode = 0;
- NTSTATUS status = NT_STATUS_OK;
+ uint32 action =
+ FILE_NOTIFY_CHANGE_LAST_ACCESS
+ |FILE_NOTIFY_CHANGE_LAST_WRITE;
- if (!params)
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
- ZERO_STRUCT(sbuf);
- ZERO_STRUCT(tvs);
+ /* get some defaults (no modifications) if any info is zero or -1. */
+ if (null_mtime(tvs.actime)) {
+ tvs.actime = psbuf->st_atime;
+ action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
+ }
- if (tran_call == TRANSACT2_SETFILEINFO) {
- if (total_params < 4) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (null_mtime(tvs.modtime)) {
+ tvs.modtime = psbuf->st_mtime;
+ action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
+ }
- fsp = file_fsp(params,0);
- info_level = SVAL(params,2);
+ DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
+ DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
- if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
- /*
- * This is actually a SETFILEINFO on a directory
- * handle (returned from an NT SMB). NT5.0 seems
- * to do this call. JRA.
- */
- pstrcpy(fname, fsp->fsp_name);
- if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
- }
- } else if (fsp && fsp->print_file) {
- /*
- * Doing a DELETE_ON_CLOSE should cancel a print job.
- */
- if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
- fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
+ /*
+ * Try and set the times of this file if
+ * they are different from the current values.
+ */
- DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
-
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
- } else
- return (UNIXERROR(ERRDOS,ERRbadpath));
- } else {
- /*
- * Original code - this is an open file.
- */
- CHECK_FSP(fsp,conn);
+ if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
+ return NT_STATUS_OK;
+ }
- pstrcpy(fname, fsp->fsp_name);
- fd = fsp->fh->fd;
+ if(fsp != NULL) {
+ /*
+ * This was a setfileinfo on an open file.
+ * NT does this a lot. We also need to
+ * set the time here, as it can be read by
+ * FindFirst/FindNext and with the patch for bug #2045
+ * in smbd/fileio.c it ensures that this timestamp is
+ * kept sticky even after a write. We save the request
+ * away and will set it on file close and after a write. JRA.
+ */
- if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
- return(UNIXERROR(ERRDOS,ERRbadfid));
- }
+ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
+ DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
+ fsp_set_pending_modtime(fsp, tvs.modtime);
}
- } else {
- /* set path info */
- if (total_params < 6) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+
+ }
+ DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
+
+ if(file_utime(conn, fname, &tvs)!=0) {
+ return map_nt_error_from_unix(errno);
+ }
+ if (action != 0) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Deal with setting the dosmode from any of the setfilepathinfo functions.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 dosmode)
+{
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (dosmode) {
+ if (S_ISDIR(psbuf->st_mode)) {
+ dosmode |= aDIR;
+ } else {
+ dosmode &= ~aDIR;
}
+ }
- info_level = SVAL(params,0);
- srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
+ DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
+
+ /* check the mode isn't different, before changing it */
+ if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
+
+ DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
+ fname, (unsigned int)dosmode ));
+
+ if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
+ DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
+ fname, strerror(errno)));
+ return map_nt_error_from_unix(errno);
}
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Deal with setting the size from any of the setfilepathinfo functions.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_size(connection_struct *conn,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ SMB_OFF_T size)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ files_struct *new_fsp = NULL;
+
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
+
+ if (size == get_file_size(*psbuf)) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
+ fname, (double)size ));
+
+ if (fsp && fsp->fh->fd != -1) {
+ /* Handle based call. */
+ if (vfs_set_filelen(fsp, size) == -1) {
+ return map_nt_error_from_unix(errno);
}
+ return NT_STATUS_OK;
+ }
- /*
- * For CIFS UNIX extensions the target name may not exist.
- */
+ status = open_file_ntcreate(conn, fname, psbuf,
+ FILE_WRITE_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ FORCE_OPLOCK_BREAK_TO_NONE,
+ NULL, &new_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /* NB. We check for open_was_deferred in the caller. */
+ return status;
+ }
- if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
- DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
- }
+ if (vfs_set_filelen(new_fsp, size) == -1) {
+ status = map_nt_error_from_unix(errno);
+ close_file(new_fsp,NORMAL_CLOSE);
+ return status;
+ }
+
+ close_file(new_fsp,NORMAL_CLOSE);
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Deal with SMB_INFO_SET_EA.
+****************************************************************************/
- if(!check_name(fname, conn)) {
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+static NTSTATUS smb_info_set_ea(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname)
+{
+ struct ea_list *ea_list = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (total_data < 10) {
+
+ /* OS/2 workplace shell seems to send SET_EA requests of "null"
+ length. They seem to have no effect. Bug #3212. JRA */
+
+ if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
+ /* We're done. We only get EA info in this call. */
+ return NT_STATUS_OK;
}
+ return NT_STATUS_INVALID_PARAMETER;
}
- if (!CAN_WRITE(conn))
- return ERROR_DOS(ERRSRV,ERRaccess);
+ if (IVAL(pdata,0) > total_data) {
+ DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
+ IVAL(pdata,0), (unsigned int)total_data));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
- return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ ctx = talloc_init("SMB_INFO_SET_EA");
+ if (!ctx) {
+ return NT_STATUS_NO_MEMORY;
}
+ ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
+ if (!ea_list) {
+ talloc_destroy(ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ status = set_ea(conn, fsp, fname, ea_list);
+ talloc_destroy(ctx);
- if (VALID_STAT(sbuf))
- unixmode = sbuf.st_mode;
+ return status;
+}
- 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));
+/****************************************************************************
+ Deal with SMB_SET_FILE_DISPOSITION_INFO.
+****************************************************************************/
- /* Realloc the parameter size */
- *pparams = SMB_REALLOC(*pparams,2);
- if (*pparams == NULL) {
- return ERROR_NT(NT_STATUS_NO_MEMORY);
+static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ BOOL delete_on_close;
+ uint32 dosmode = 0;
+
+ if (total_data < 1) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- params = *pparams;
- SSVAL(params,0,0);
+ if (fsp == NULL) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
- if (fsp && fsp->pending_modtime) {
- /* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp->pending_modtime;
+ delete_on_close = (CVAL(pdata,0) ? True : False);
+ dosmode = dos_mode(conn, fname, psbuf);
+
+ status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- size = get_file_size(sbuf);
- tvs.modtime = sbuf.st_mtime;
- tvs.actime = sbuf.st_atime;
- dosmode = dos_mode(conn,fname,&sbuf);
- unixmode = sbuf.st_mode;
+ /* The set is across all open files on this dev/inode pair. */
+ if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
- set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
- set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
+/****************************************************************************
+ Deal with SMB_FILE_POSITION_INFORMATION.
+****************************************************************************/
- switch (info_level) {
- case SMB_INFO_STANDARD:
- {
- if (total_data < 12) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+static NTSTATUS smb_file_position_information(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp)
+{
+ SMB_BIG_UINT position_information;
- /* access time */
- tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
- /* write time */
- tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
- break;
- }
+ if (total_data < 8) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- case SMB_INFO_SET_EA:
- {
- struct ea_list *ea_list = NULL;
- TALLOC_CTX *ctx = NULL;
+ if (fsp == NULL) {
+ /* Ignore on pathname based set. */
+ return NT_STATUS_OK;
+ }
- if (total_data < 10) {
+ position_information = (SMB_BIG_UINT)IVAL(pdata,0);
+#ifdef LARGE_SMB_OFF_T
+ position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
+#else /* LARGE_SMB_OFF_T */
+ if (IVAL(pdata,4) != 0) {
+ /* more than 32 bits? */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+#endif /* LARGE_SMB_OFF_T */
- /* OS/2 workplace shell seems to send SET_EA requests of "null"
- length. They seem to have no effect. Bug #3212. JRA */
+ DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
+ fsp->fsp_name, (double)position_information ));
+ fsp->fh->position_information = position_information;
+ return NT_STATUS_OK;
+}
- if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
- /* 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);
- }
+/****************************************************************************
+ Deal with SMB_FILE_MODE_INFORMATION.
+****************************************************************************/
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+static NTSTATUS smb_file_mode_information(connection_struct *conn,
+ const char *pdata,
+ int total_data)
+{
+ uint32 mode;
- 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);
- }
+ if (total_data < 4) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ mode = IVAL(pdata,0);
+ if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ return NT_STATUS_OK;
+}
- 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);
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
+****************************************************************************/
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
+static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
+ char *inbuf,
+ const char *pdata,
+ int total_data,
+ const char *fname)
+{
+ pstring link_target;
+ const char *newname = fname;
+ NTSTATUS status = NT_STATUS_OK;
- /* 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);
+ /* Set a symbolic link. */
+ /* Don't allow this if follow links is false. */
+
+ if (total_data == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!lp_symlinks(SNUM(conn))) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
+
+ /* !widelinks forces the target path to be within the share. */
+ /* This means we can interpret the target as a pathname. */
+ if (!lp_widelinks(SNUM(conn))) {
+ pstring rel_name;
+ char *last_dirp = NULL;
+
+ unix_format(link_target);
+ if (*link_target == '/') {
+ /* No absolute paths allowed. */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ pstrcpy(rel_name, newname);
+ last_dirp = strrchr_m(rel_name, '/');
+ if (last_dirp) {
+ last_dirp[1] = '\0';
+ } else {
+ pstrcpy(rel_name, "./");
}
+ pstrcat(rel_name, link_target);
-#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_NT(NT_STATUS_INVALID_PARAMETER);
+ status = check_name(conn, rel_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
- tvs.actime = make_unix_date2(pdata+8);
- tvs.modtime = make_unix_date2(pdata+12);
- size = IVAL(pdata,16);
- dosmode = IVAL(pdata,24);
- break;
+ DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
+ newname, link_target ));
- /* XXXX nor this. not in cifs6.txt, either. */
- case SMB_INFO_QUERY_ALL_EAS:
- if (total_data < 28)
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
- tvs.actime = make_unix_date2(pdata+8);
- tvs.modtime = make_unix_date2(pdata+12);
- size = IVAL(pdata,16);
- dosmode = IVAL(pdata,24);
- break;
-#endif
+ return NT_STATUS_OK;
+}
- case SMB_SET_FILE_BASIC_INFO:
- case SMB_FILE_BASIC_INFORMATION:
- {
- /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
- time_t write_time;
- time_t changed_time;
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
+****************************************************************************/
- if (total_data < 36) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
+ char *inbuf,
+ char *outbuf,
+ const char *pdata,
+ int total_data,
+ pstring fname)
+{
+ pstring oldname;
+ NTSTATUS status = NT_STATUS_OK;
- /* Ignore create time at offset pdata. */
+ /* Set a hard link. */
+ if (total_data == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- /* access time */
- tvs.actime = interpret_long_date(pdata+8);
+ srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- write_time = interpret_long_date(pdata+16);
- changed_time = interpret_long_date(pdata+24);
+ RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
- tvs.modtime = MIN(write_time, changed_time);
+ DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
+ fname, oldname));
- if (write_time > tvs.modtime && write_time != (time_t)-1) {
- tvs.modtime = write_time;
- }
- /* Prefer a defined time to an undefined one. */
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
- }
+ return hardlink_internals(conn, oldname, fname);
+}
- /* attributes */
- dosmode = IVAL(pdata,32);
- break;
- }
+/****************************************************************************
+ Deal with SMB_FILE_RENAME_INFORMATION.
+****************************************************************************/
- case SMB_FILE_ALLOCATION_INFORMATION:
- case SMB_SET_FILE_ALLOCATION_INFO:
- {
- int ret = -1;
- SMB_BIG_UINT allocation_size;
+static NTSTATUS smb_file_rename_information(connection_struct *conn,
+ char *inbuf,
+ char *outbuf,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ pstring fname)
+{
+ BOOL overwrite;
+ /* uint32 root_fid; */ /* Not used */
+ uint32 len;
+ pstring newname;
+ pstring base_name;
+ NTSTATUS status = NT_STATUS_OK;
+ char *p;
- if (total_data < 8) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (total_data < 13) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
- allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
-#endif /* LARGE_SMB_OFF_T */
- DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
- fname, (double)allocation_size ));
+ overwrite = (CVAL(pdata,0) ? True : False);
+ /* root_fid = IVAL(pdata,4); */
+ len = IVAL(pdata,8);
- if (allocation_size) {
- allocation_size = smb_roundup(conn, allocation_size);
- }
+ if (len > (total_data - 12) || (len == 0)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- if(allocation_size != get_file_size(sbuf)) {
- SMB_STRUCT_STAT new_sbuf;
-
- DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
- fname, (double)allocation_size ));
-
- if (fd == -1) {
- files_struct *new_fsp = NULL;
-
- new_fsp = open_file_ntcreate(conn, fname, &sbuf,
- FILE_WRITE_DATA,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- FORCE_OPLOCK_BREAK_TO_NONE,
- NULL);
-
- if (new_fsp == NULL) {
- if (open_was_deferred(SVAL(inbuf,smb_mid))) {
- /* We have re-scheduled this call. */
- return -1;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- ret = vfs_allocate_file_space(new_fsp, allocation_size);
- if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
- new_fsp->fnum, strerror(errno)));
- ret = -1;
- }
- close_file(new_fsp,NORMAL_CLOSE);
- } else {
- ret = vfs_allocate_file_space(fsp, allocation_size);
- if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
- fsp->fnum, strerror(errno)));
- ret = -1;
- }
- }
- if (ret == -1)
- return ERROR_NT(NT_STATUS_DISK_FULL);
+ srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- /* Allocate can truncate size... */
- size = get_file_size(new_sbuf);
- }
+ RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
- break;
- }
+ /* Check the new name has no '/' characters. */
+ if (strchr_m(newname, '/')) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
- case SMB_FILE_END_OF_FILE_INFORMATION:
- case SMB_SET_FILE_END_OF_FILE_INFO:
- {
- if (total_data < 8) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ /* Create the base directory. */
+ pstrcpy(base_name, fname);
+ p = strrchr_m(base_name, '/');
+ if (p) {
+ *p = '\0';
+ }
+ /* Append the new name. */
+ pstrcat(base_name, "/");
+ pstrcat(base_name, newname);
- size = IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ if (fsp) {
+ DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
+ fsp->fnum, fsp->fsp_name, base_name ));
+ status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
+ } else {
+ DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
+ fname, newname ));
+ status = rename_internals(conn, fname, base_name, 0, overwrite, False);
+ }
+
+ return status;
+}
+
+/****************************************************************************
+ Deal with SMB_SET_POSIX_ACL.
+****************************************************************************/
+
+#if defined(HAVE_POSIX_ACLS)
+static NTSTATUS smb_set_posix_acl(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ uint16 posix_acl_version;
+ uint16 num_file_acls;
+ uint16 num_def_acls;
+ BOOL valid_file_acls = True;
+ BOOL valid_def_acls = True;
+
+ if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ posix_acl_version = SVAL(pdata,0);
+ num_file_acls = SVAL(pdata,2);
+ num_def_acls = SVAL(pdata,4);
+
+ if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
+ valid_file_acls = False;
+ num_file_acls = 0;
+ }
+
+ if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
+ valid_def_acls = False;
+ num_def_acls = 0;
+ }
+
+ if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
+ (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE +
+ (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
+ return map_nt_error_from_unix(errno);
+ }
+ return NT_STATUS_OK;
+}
+#endif
+
+/****************************************************************************
+ Deal with SMB_SET_POSIX_LOCK.
+****************************************************************************/
+
+static NTSTATUS smb_set_posix_lock(connection_struct *conn,
+ char *inbuf,
+ int length,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp)
+{
+ SMB_BIG_UINT count;
+ SMB_BIG_UINT offset;
+ uint32 lock_pid;
+ BOOL blocking_lock = False;
+ enum brl_type lock_type;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (fsp == NULL || fsp->fh->fd == -1) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
+ case POSIX_LOCK_TYPE_READ:
+ lock_type = READ_LOCK;
+ break;
+ case POSIX_LOCK_TYPE_WRITE:
+ /* Return the right POSIX-mappable error code for files opened read-only. */
+ if (!fsp->can_write) {
+ return NT_STATUS_INVALID_HANDLE;
}
-#endif /* LARGE_SMB_OFF_T */
- DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
+ lock_type = WRITE_LOCK;
break;
- }
+ case POSIX_LOCK_TYPE_UNLOCK:
+ lock_type = UNLOCK_LOCK;
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- case SMB_FILE_DISPOSITION_INFORMATION:
- case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
- {
- BOOL delete_on_close;
+ if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
+ blocking_lock = False;
+ } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
+ blocking_lock = True;
+ } else {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- if (total_data < 1) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ if (!lp_blocking_locks(SNUM(conn))) {
+ blocking_lock = False;
+ }
+
+ lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
+#if defined(HAVE_LONGLONG)
+ offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
+ ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
+ count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
+ ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
+#else /* HAVE_LONGLONG */
+ offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
+ count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
+#endif /* HAVE_LONGLONG */
+
+ if (lock_type == UNLOCK_LOCK) {
+ status = do_unlock(fsp,
+ lock_pid,
+ count,
+ offset,
+ POSIX_LOCK);
+ } else {
+ struct byte_range_lock *br_lck = do_lock(fsp,
+ lock_pid,
+ count,
+ offset,
+ lock_type,
+ POSIX_LOCK,
+ blocking_lock,
+ &status);
+
+ if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(br_lck,
+ inbuf, length,
+ fsp,
+ -1, /* infinite timeout. */
+ 0,
+ lock_pid,
+ lock_type,
+ POSIX_LOCK,
+ offset,
+ count)) {
+ TALLOC_FREE(br_lck);
+ return status;
}
+ }
+ TALLOC_FREE(br_lck);
+ }
- delete_on_close = (CVAL(pdata,0) ? True : False);
+ return status;
+}
- /* Just ignore this set on a path. */
- if (tran_call != TRANSACT2_SETFILEINFO)
- break;
+/****************************************************************************
+ Deal with SMB_INFO_STANDARD.
+****************************************************************************/
- if (fsp == NULL)
- return(UNIXERROR(ERRDOS,ERRbadfid));
+static NTSTATUS smb_set_info_standard(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ const SMB_STRUCT_STAT *psbuf)
+{
+ struct utimbuf tvs;
- status = can_set_delete_on_close(fsp, delete_on_close,
- dosmode);
-
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
+ if (total_data < 12) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- /* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
- return ERROR_NT(NT_STATUS_ACCESS_DENIED);
- }
+ /* access time */
+ tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
+ /* write time */
+ tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
- }
+ return smb_set_file_time(conn,
+ fsp,
+ fname,
+ psbuf,
+ tvs);
+}
- case SMB_FILE_POSITION_INFORMATION:
- {
- SMB_BIG_UINT position_information;
+/****************************************************************************
+ Deal with SMB_SET_FILE_BASIC_INFO.
+****************************************************************************/
- if (total_data < 8) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
+ time_t write_time;
+ time_t changed_time;
+ uint32 dosmode = 0;
+ struct utimbuf tvs;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (total_data < 36) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Set the attributes */
+ dosmode = IVAL(pdata,32);
+ status = smb_set_file_dosmode(conn,
+ fname,
+ psbuf,
+ dosmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Ignore create time at offset pdata. */
+
+ /* access time */
+ tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
+
+ write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
+ changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
+
+ tvs.modtime = MIN(write_time, changed_time);
+
+ if (write_time > tvs.modtime && write_time != (time_t)-1) {
+ tvs.modtime = write_time;
+ }
+ /* Prefer a defined time to an undefined one. */
+ if (null_mtime(tvs.modtime)) {
+ tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+ }
- position_information = (SMB_BIG_UINT)IVAL(pdata,0);
+ return smb_set_file_time(conn,
+ fsp,
+ fname,
+ psbuf,
+ tvs);
+}
+
+/****************************************************************************
+ Deal with SMB_SET_FILE_ALLOCATION_INFO.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ SMB_BIG_UINT allocation_size = 0;
+ NTSTATUS status = NT_STATUS_OK;
+ files_struct *new_fsp = NULL;
+
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (total_data < 8) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
#ifdef LARGE_SMB_OFF_T
- position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
+ allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (IVAL(pdata,4) != 0) {
+ /* more than 32 bits? */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
#endif /* LARGE_SMB_OFF_T */
- DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
- fname, (double)position_information ));
- if (fsp) {
- fsp->fh->position_information = position_information;
- }
- /* 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);
- }
+ DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
+ fname, (double)allocation_size ));
- /* 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?).
- */
+ if (allocation_size) {
+ allocation_size = smb_roundup(conn, allocation_size);
+ }
- case SMB_FILE_MODE_INFORMATION:
- {
- uint32 mode;
+ if(allocation_size == get_file_size(*psbuf)) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
+ fname, (double)allocation_size ));
+
+ if (fsp && fsp->fh->fd != -1) {
+ /* Open file handle. */
+ if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ return NT_STATUS_OK;
+ }
- 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);
- }
+ /* Pathname or stat or directory file. */
- /* 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);
- }
+ status = open_file_ntcreate(conn, fname, psbuf,
+ FILE_WRITE_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ FORCE_OPLOCK_BREAK_TO_NONE,
+ NULL, &new_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /* NB. We check for open_was_deferred in the caller. */
+ return status;
+ }
+ if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
+ status = map_nt_error_from_unix(errno);
+ close_file(new_fsp,NORMAL_CLOSE);
+ return status;
+ }
- /*
- * CIFS UNIX extensions.
- */
+ close_file(new_fsp,NORMAL_CLOSE);
+ return NT_STATUS_OK;
+}
- case SMB_SET_FILE_UNIX_BASIC:
- {
- uint32 raw_unixmode;
+/****************************************************************************
+ Deal with SMB_SET_FILE_END_OF_FILE_INFO.
+****************************************************************************/
- if (total_data < 100) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ SMB_OFF_T size;
- if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
- IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
- size=IVAL(pdata,0); /* first 8 Bytes are size */
+ if (total_data < 8) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ size = IVAL(pdata,0);
#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
+ size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (IVAL(pdata,4) != 0) {
+ /* more than 32 bits? */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
#endif /* LARGE_SMB_OFF_T */
- }
- pdata+=24; /* ctime & st_blocks are not changed */
- tvs.actime = interpret_long_date(pdata); /* access_time */
- tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
- pdata+=16;
- set_owner = (uid_t)IVAL(pdata,0);
- pdata += 8;
- set_grp = (gid_t)IVAL(pdata,0);
- pdata += 8;
- raw_unixmode = IVAL(pdata,28);
- unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
- dosmode = 0; /* Ensure dos mode change doesn't override this. */
-
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
-size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
- fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
-
- if (!VALID_STAT(sbuf)) {
+ DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
+ "file %s to %.0f\n", fname, (double)size ));
+
+ return smb_set_file_size(conn,
+ fsp,
+ fname,
+ psbuf,
+ size);
+}
- /*
- * The only valid use of this is to create character and block
- * devices, and named pipes. This is deprecated (IMHO) and
- * a new info level should be used for mknod. JRA.
- */
+/****************************************************************************
+ Allow a UNIX info mknod.
+****************************************************************************/
- uint32 file_type = IVAL(pdata,0);
+static NTSTATUS smb_unix_mknod(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ uint32 file_type = IVAL(pdata,56);
#if defined(HAVE_MAKEDEV)
- uint32 dev_major = IVAL(pdata,4);
- uint32 dev_minor = IVAL(pdata,12);
+ uint32 dev_major = IVAL(pdata,60);
+ uint32 dev_minor = IVAL(pdata,68);
#endif
+ SMB_DEV_T dev = (SMB_DEV_T)0;
+ uint32 raw_unixmode = IVAL(pdata,84);
+ NTSTATUS status;
+ mode_t unixmode;
- uid_t myuid = geteuid();
- gid_t mygid = getegid();
- SMB_DEV_T dev = (SMB_DEV_T)0;
-
- if (tran_call == TRANSACT2_SETFILEINFO)
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ if (total_data < 100) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- if (raw_unixmode == SMB_MODE_NO_CHANGE) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
#if defined(HAVE_MAKEDEV)
- dev = makedev(dev_major, dev_minor);
+ dev = makedev(dev_major, dev_minor);
#endif
- /* We can only create as the owner/group we are. */
-
- if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
- if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
-
- switch (file_type) {
+ switch (file_type) {
#if defined(S_IFIFO)
- case UNIX_TYPE_FIFO:
- unixmode |= S_IFIFO;
- break;
+ case UNIX_TYPE_FIFO:
+ unixmode |= S_IFIFO;
+ break;
#endif
#if defined(S_IFSOCK)
- case UNIX_TYPE_SOCKET:
- unixmode |= S_IFSOCK;
- break;
+ case UNIX_TYPE_SOCKET:
+ unixmode |= S_IFSOCK;
+ break;
#endif
#if defined(S_IFCHR)
- case UNIX_TYPE_CHARDEV:
- unixmode |= S_IFCHR;
- break;
+ case UNIX_TYPE_CHARDEV:
+ unixmode |= S_IFCHR;
+ break;
#endif
#if defined(S_IFBLK)
- case UNIX_TYPE_BLKDEV:
- unixmode |= S_IFBLK;
- break;
+ case UNIX_TYPE_BLKDEV:
+ unixmode |= S_IFBLK;
+ break;
#endif
- default:
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
- }
-
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
-0%o for file %s\n", (double)dev, unixmode, fname ));
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- /* Ok - do the mknod. */
- if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
+0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
- inherit_access_acl(conn, fname, unixmode);
+ /* Ok - do the mknod. */
+ if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
- }
+ /* If any of the other "set" calls fail we
+ * don't want to end up with a half-constructed mknod.
+ */
- /*
- * Deal with the UNIX specific mode set.
- */
+ if (lp_inherit_perms(SNUM(conn))) {
+ inherit_access_acl(
+ conn, parent_dirname(fname),
+ fname, unixmode);
+ }
- if (raw_unixmode != SMB_MODE_NO_CHANGE) {
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
- (unsigned int)unixmode, fname ));
- if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ status = map_nt_error_from_unix(errno);
+ SMB_VFS_UNLINK(conn,fname);
+ return status;
+ }
+ return NT_STATUS_OK;
+}
- /*
- * Deal with the UNIX specific uid set.
- */
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_BASIC.
+****************************************************************************/
- if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
- (unsigned int)set_owner, fname ));
- if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ struct utimbuf tvs;
+ uint32 raw_unixmode;
+ mode_t unixmode;
+ SMB_OFF_T size = 0;
+ uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
+ gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
+ NTSTATUS status = NT_STATUS_OK;
+ BOOL delete_on_fail = False;
+ enum perm_type ptype;
- /*
- * Deal with the UNIX specific gid set.
- */
+ if (total_data < 100) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
- (unsigned int)set_owner, fname ));
- if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- break;
+ if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
+ IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
+ size=IVAL(pdata,0); /* first 8 Bytes are size */
+#ifdef LARGE_SMB_OFF_T
+ size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
+#else /* LARGE_SMB_OFF_T */
+ if (IVAL(pdata,4) != 0) {
+ /* more than 32 bits? */
+ return NT_STATUS_INVALID_PARAMETER;
}
+#endif /* LARGE_SMB_OFF_T */
+ }
- case SMB_SET_FILE_UNIX_LINK:
- {
- pstring link_target;
- char *newname = fname;
+ tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
+ tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
+ set_owner = (uid_t)IVAL(pdata,40);
+ set_grp = (gid_t)IVAL(pdata,48);
+ raw_unixmode = IVAL(pdata,84);
- /* Set a symbolic link. */
- /* Don't allow this if follow links is false. */
+ if (VALID_STAT(*psbuf)) {
+ if (S_ISDIR(psbuf->st_mode)) {
+ ptype = PERM_EXISTING_DIR;
+ } else {
+ ptype = PERM_EXISTING_FILE;
+ }
+ } else {
+ ptype = PERM_NEW_FILE;
+ }
- if (!lp_symlinks(SNUM(conn)))
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
+size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
+ fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
- /* !widelinks forces the target path to be within the share. */
- /* This means we can interpret the target as a pathname. */
- if (!lp_widelinks(SNUM(conn))) {
- pstring rel_name;
- char *last_dirp = NULL;
+ if (!VALID_STAT(*psbuf)) {
+ /*
+ * The only valid use of this is to create character and block
+ * devices, and named pipes. This is deprecated (IMHO) and
+ * a new info level should be used for mknod. JRA.
+ */
- unix_format(link_target);
- if (*link_target == '/') {
- /* No absolute paths allowed. */
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- pstrcpy(rel_name, newname);
- last_dirp = strrchr_m(rel_name, '/');
- if (last_dirp) {
- last_dirp[1] = '\0';
- } else {
- pstrcpy(rel_name, "./");
- }
- pstrcat(rel_name, link_target);
+ status = smb_unix_mknod(conn,
+ pdata,
+ total_data,
+ fname,
+ psbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- if (!check_name(rel_name, conn)) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- }
+ /* Ensure we don't try and change anything else. */
+ raw_unixmode = SMB_MODE_NO_CHANGE;
+ size = get_file_size(*psbuf);
+ tvs.modtime = psbuf->st_mtime;
+ tvs.actime = psbuf->st_atime;
+ /*
+ * We continue here as we might want to change the
+ * owner uid/gid.
+ */
+ delete_on_fail = True;
+ }
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
- fname, link_target ));
+ /*
+ * Deal with the UNIX specific mode set.
+ */
- if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ if (raw_unixmode != SMB_MODE_NO_CHANGE) {
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
+ (unsigned int)unixmode, fname ));
+ if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
+ return map_nt_error_from_unix(errno);
}
+ }
- case SMB_SET_FILE_UNIX_HLINK:
- {
- pstring oldname;
- char *newname = fname;
+ /*
+ * Deal with the UNIX specific uid set.
+ */
- /* Set a hard link. */
- srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
+ if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
+ (unsigned int)set_owner, fname ));
+ if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
+ status = map_nt_error_from_unix(errno);
+ if (delete_on_fail) {
+ SMB_VFS_UNLINK(conn,fname);
}
+ return status;
+ }
+ }
- DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
- fname, oldname));
+ /*
+ * Deal with the UNIX specific gid set.
+ */
- status = hardlink_internals(conn, oldname, newname);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
+ if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
+ (unsigned int)set_owner, fname ));
+ if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
+ status = map_nt_error_from_unix(errno);
+ if (delete_on_fail) {
+ SMB_VFS_UNLINK(conn,fname);
}
-
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ return status;
}
+ }
- case SMB_FILE_RENAME_INFORMATION:
- {
- BOOL overwrite;
- uint32 root_fid;
- uint32 len;
- pstring newname;
- pstring base_name;
- char *p;
+ /* Deal with any size changes. */
- if (total_data < 12) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ status = smb_set_file_size(conn,
+ fsp,
+ fname,
+ psbuf,
+ size);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- overwrite = (CVAL(pdata,0) ? True : False);
- root_fid = IVAL(pdata,4);
- len = IVAL(pdata,8);
- srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
+ /* Deal with any time changes. */
- /* Check the new name has no '/' characters. */
- if (strchr_m(newname, '/'))
- return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
-
- RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
-
- /* Create the base directory. */
- pstrcpy(base_name, fname);
- p = strrchr_m(base_name, '/');
- if (p)
- *p = '\0';
- /* Append the new name. */
- pstrcat(base_name, "/");
- pstrcat(base_name, newname);
-
- if (fsp) {
- DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp->fsp_name, base_name ));
- status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
- } else {
- DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
- fname, newname ));
- status = rename_internals(conn, fname, base_name, 0, overwrite, False);
- }
+ return smb_set_file_time(conn,
+ fsp,
+ fname,
+ psbuf,
+ tvs);
+}
- if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(SVAL(inbuf,smb_mid))) {
- /* We have re-scheduled this call. */
- return -1;
- }
- return ERROR_NT(status);
- }
+/****************************************************************************
+ Create a directory with POSIX semantics.
+****************************************************************************/
+
+static NTSTATUS smb_posix_mkdir(connection_struct *conn,
+ char **ppdata,
+ int total_data,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ int *pdata_return_size)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ uint32 raw_unixmode = 0;
+ uint32 mod_unixmode = 0;
+ mode_t unixmode = (mode_t)0;
+ files_struct *fsp = NULL;
+ uint16 info_level_return = 0;
+ char *pdata = *ppdata;
+
+ if (total_data < 10) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ raw_unixmode = IVAL(pdata,8);
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+
+ status = open_directory(conn,
+ fname,
+ psbuf,
+ FILE_READ_ATTRIBUTES, /* Just a stat open */
+ FILE_SHARE_NONE, /* Ignored for stat opens */
+ FILE_CREATE,
+ 0,
+ mod_unixmode,
+ NULL,
+ &fsp);
+
+ if (NT_STATUS_IS_OK(status)) {
+ close_file(fsp, NORMAL_CLOSE);
+ }
+
+ info_level_return = SVAL(pdata,12);
+
+ if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
+ *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else {
+ *pdata_return_size = 8;
+ }
+
+ /* Realloc the data size */
+ *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
+ if (*ppdata == NULL) {
+ *pdata_return_size = 0;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ SSVAL(pdata,0,NO_OPLOCK_RETURN);
+ SSVAL(pdata,2,0);
+
+ if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
+ SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,6,0); /* Padding. */
+ store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
+ } else {
+ SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,6,0); /* Padding. */
+ }
+
+ return status;
+}
+
+/****************************************************************************
+ Open/Create a file with POSIX semantics.
+****************************************************************************/
+
+static NTSTATUS smb_posix_open(connection_struct *conn,
+ char **ppdata,
+ int total_data,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ int *pdata_return_size)
+{
+ BOOL extended_oplock_granted = False;
+ char *pdata = *ppdata;
+ uint32 flags = 0;
+ uint32 wire_open_mode = 0;
+ uint32 raw_unixmode = 0;
+ uint32 mod_unixmode = 0;
+ uint32 create_disp = 0;
+ uint32 access_mask = 0;
+ uint32 create_options = 0;
+ NTSTATUS status = NT_STATUS_OK;
+ mode_t unixmode = (mode_t)0;
+ files_struct *fsp = NULL;
+ int oplock_request = 0;
+ int info = 0;
+ uint16 info_level_return = 0;
+
+ if (total_data < 14) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ flags = IVAL(pdata,0);
+ oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
+ if (oplock_request) {
+ oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+ }
+
+ wire_open_mode = IVAL(pdata,4);
+
+ if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
+ return smb_posix_mkdir(conn,
+ ppdata,
+ total_data,
+ fname,
+ psbuf,
+ pdata_return_size);
+ }
+
+ switch (wire_open_mode & SMB_ACCMODE) {
+ case SMB_O_RDONLY:
+ access_mask = FILE_READ_DATA;
+ break;
+ case SMB_O_WRONLY:
+ access_mask = FILE_WRITE_DATA;
+ break;
+ case SMB_O_RDWR:
+ access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
+ break;
+ default:
+ DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
+ (unsigned int)wire_open_mode ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ wire_open_mode &= ~SMB_ACCMODE;
+
+ if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
+ create_disp = FILE_CREATE;
+ } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
+ create_disp = FILE_OVERWRITE_IF;
+ } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
+ create_disp = FILE_OPEN_IF;
+ } else {
+ DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
+ (unsigned int)wire_open_mode ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ raw_unixmode = IVAL(pdata,8);
+ status = unix_perms_from_wire(conn,
+ psbuf,
+ raw_unixmode,
+ VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
+ &unixmode);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+
+ if (wire_open_mode & SMB_O_SYNC) {
+ create_options |= FILE_WRITE_THROUGH;
+ }
+ if (wire_open_mode & SMB_O_APPEND) {
+ access_mask |= FILE_APPEND_DATA;
+ }
+ if (wire_open_mode & SMB_O_DIRECT) {
+ mod_unixmode |= FILE_FLAG_NO_BUFFERING;
+ }
+
+ status = open_file_ntcreate(conn,
+ fname,
+ psbuf,
+ access_mask,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ create_disp,
+ 0, /* no create options yet. */
+ mod_unixmode,
+ oplock_request,
+ &info,
+ &fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
+ extended_oplock_granted = True;
+ }
- process_pending_change_notify_queue((time_t)0);
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+ extended_oplock_granted = True;
+ }
+
+ info_level_return = SVAL(pdata,12);
+
+ if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
+ *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else {
+ *pdata_return_size = 8;
+ }
+
+ /* Realloc the data size */
+ *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
+ if (*ppdata == NULL) {
+ close_file(fsp,ERROR_CLOSE);
+ *pdata_return_size = 0;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (extended_oplock_granted) {
+ if (flags & REQUEST_BATCH_OPLOCK) {
+ SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
+ } else {
+ SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
}
+ } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
+ SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
+ } else {
+ SSVAL(pdata,0,NO_OPLOCK_RETURN);
+ }
-#if defined(HAVE_POSIX_ACLS)
- case SMB_SET_POSIX_ACL:
- {
- uint16 posix_acl_version;
- uint16 num_file_acls;
- uint16 num_def_acls;
- BOOL valid_file_acls = True;
- BOOL valid_def_acls = True;
+ SSVAL(pdata,2,fsp->fnum);
+ if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
+ SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,6,0); /* padding. */
+ store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
+ } else {
+ SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,6,0); /* padding. */
+ }
+ return NT_STATUS_OK;
+}
- if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- posix_acl_version = SVAL(pdata,0);
- num_file_acls = SVAL(pdata,2);
- num_def_acls = SVAL(pdata,4);
+/****************************************************************************
+ Delete a file with POSIX semantics.
+****************************************************************************/
- if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
- valid_file_acls = False;
- num_file_acls = 0;
- }
+static NTSTATUS smb_posix_unlink(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ files_struct *fsp = NULL;
+ int info = 0;
- if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
- valid_def_acls = False;
- num_def_acls = 0;
- }
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
- if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (VALID_STAT_OF_DIR(*psbuf)) {
+ status = open_directory(conn,
+ fname,
+ psbuf,
+ DELETE_ACCESS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_DELETE_ON_CLOSE,
+ FILE_FLAG_POSIX_SEMANTICS|0777,
+ &info,
+ &fsp);
+ } else {
+ status = open_file_ntcreate(conn,
+ fname,
+ psbuf,
+ DELETE_ACCESS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_DELETE_ON_CLOSE,
+ FILE_FLAG_POSIX_SEMANTICS|0777,
+ INTERNAL_OPEN_ONLY,
+ &info,
+ &fsp);
+ }
- if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
- (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return close_file(fsp, NORMAL_CLOSE);
+}
- if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
- pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+/****************************************************************************
+ Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
+****************************************************************************/
- if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
- pdata + SMB_POSIX_ACL_HEADER_SIZE +
- (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ unsigned int tran_call,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
+{
+ char *params = *pparams;
+ char *pdata = *ppdata;
+ uint16 info_level;
+ SMB_STRUCT_STAT sbuf;
+ pstring fname;
+ files_struct *fsp = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+ int data_return_size = 0;
+
+ if (!params) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ ZERO_STRUCT(sbuf);
+
+ if (tran_call == TRANSACT2_SETFILEINFO) {
+ if (total_params < 4) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
-#endif
-#if defined(DEVELOPER)
- case SMB_SET_POSIX_LOCK:
- {
- SMB_BIG_UINT count;
- SMB_BIG_UINT offset;
- uint16 lock_pid;
- BOOL lock_blocking;
- enum brl_type lock_type;
- BOOL my_lock_ctx;
+ fsp = file_fsp(params,0);
+ info_level = SVAL(params,2);
- if (fsp == NULL || fsp->fh->fd == -1) {
- return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+ if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+ /*
+ * This is actually a SETFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+ pstrcpy(fname, fsp->fsp_name);
+ if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ return UNIXERROR(ERRDOS,ERRbadpath);
}
+ } else if (fsp && fsp->print_file) {
+ /*
+ * Doing a DELETE_ON_CLOSE should cancel a print job.
+ */
+ if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
+ fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
- if (total_data != POSIX_LOCK_DATA_SIZE) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
+
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
+ return(-1);
+ } else
+ return (UNIXERROR(ERRDOS,ERRbadpath));
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+ CHECK_FSP(fsp,conn);
- switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
- case POSIX_LOCK_TYPE_READ:
- lock_type = READ_LOCK;
- break;
- case POSIX_LOCK_TYPE_WRITE:
- /* Return the right POSIX-mappable error code for files opened read-only. */
- if (!fsp->can_write) {
- return ERROR_NT(NT_STATUS_INVALID_HANDLE);
- }
- lock_type = WRITE_LOCK;
- break;
- case POSIX_LOCK_TYPE_UNLOCK:
- lock_type = UNLOCK_LOCK;
- break;
- default:
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ pstrcpy(fname, fsp->fsp_name);
- if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
- lock_blocking = False;
- } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
- lock_blocking = True;
- } else {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ return(UNIXERROR(ERRDOS,ERRbadfid));
}
+ }
+ } else {
+ /* set path info */
+ if (total_params < 7) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
-#if defined(HAVE_LONGLONG)
- offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
- ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
- count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
- ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
-#else /* HAVE_LONGLONG */
- offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
- count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
-#endif /* HAVE_LONGLONG */
+ info_level = SVAL(params,0);
+ srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
- if (lock_type == UNLOCK_LOCK) {
- status = do_unlock(fsp,
- lock_pid,
- count,
- offset,
- POSIX_LOCK);
- } else {
- status = do_lock(fsp,
- lock_pid,
- count,
- offset,
- lock_type,
- POSIX_LOCK,
- &my_lock_ctx);
-
- if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length,
- fsp,
- -1, /* infinite timeout. */
- 0,
- lock_pid,
- lock_type,
- POSIX_LOCK,
- offset,
- count)) {
- return -1;
- }
- }
- }
+ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
+ status = unix_convert(conn, fname, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
- SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ /*
+ * For CIFS UNIX extensions the target name may not exist.
+ */
+
+ if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
+ DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
+ return UNIXERROR(ERRDOS,ERRbadpath);
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
-#endif
- default:
- return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- /* get some defaults (no modifications) if any info is zero or -1. */
- if (null_mtime(tvs.actime)) {
- tvs.actime = sbuf.st_atime;
+ if (!CAN_WRITE(conn)) {
+ return ERROR_DOS(ERRSRV,ERRaccess);
}
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = sbuf.st_mtime;
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
- DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
- DEBUG(6,("size: %.0f ", (double)size));
+ 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));
- if (dosmode) {
- if (S_ISDIR(sbuf.st_mode))
- dosmode |= aDIR;
- else
- dosmode &= ~aDIR;
+ /* Realloc the parameter size */
+ *pparams = (char *)SMB_REALLOC(*pparams,2);
+ if (*pparams == NULL) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
}
+ params = *pparams;
- DEBUG(6,("dosmode: %x\n" , dosmode));
-
- if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
- (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
- (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
- (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
+ SSVAL(params,0,0);
- /*
- * Only do this test if we are not explicitly
- * changing the size of a file.
- */
- if (!size)
- size = get_file_size(sbuf);
+ if (fsp && fsp->pending_modtime) {
+ /* the pending modtime overrides the current modtime */
+ sbuf.st_mtime = fsp->pending_modtime;
}
- /*
- * Try and set the times, size and mode of this file -
- * if they are different from the current values
- */
+ switch (info_level) {
- /* check the mode isn't different, before changing it */
- if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
+ case SMB_INFO_STANDARD:
+ {
+ status = smb_set_info_standard(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
- DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
+ case SMB_INFO_SET_EA:
+ {
+ status = smb_info_set_ea(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname);
+ break;
+ }
- if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
- DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ case SMB_SET_FILE_BASIC_INFO:
+ case SMB_FILE_BASIC_INFORMATION:
+ {
+ status = smb_set_file_basic_info(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
}
- }
- /* Now the size. */
- if (size != get_file_size(sbuf)) {
+ case SMB_FILE_ALLOCATION_INFORMATION:
+ case SMB_SET_FILE_ALLOCATION_INFO:
+ {
+ status = smb_set_file_allocation_info(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
- int ret;
+ case SMB_FILE_END_OF_FILE_INFORMATION:
+ case SMB_SET_FILE_END_OF_FILE_INFO:
+ {
+ status = smb_set_file_end_of_file_info(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
- DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
- fname, (double)size ));
+ case SMB_FILE_DISPOSITION_INFORMATION:
+ case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
+ {
+#if 0
+ /* JRA - We used to just ignore this on a path ?
+ * Shouldn't this be invalid level on a pathname
+ * based call ?
+ */
+ if (tran_call != TRANSACT2_SETFILEINFO) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+#endif
+ status = smb_set_file_disposition_info(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
- if (fd == -1) {
- files_struct *new_fsp = NULL;
+ case SMB_FILE_POSITION_INFORMATION:
+ {
+ status = smb_file_position_information(conn,
+ pdata,
+ total_data,
+ fsp);
+ break;
+ }
- new_fsp = open_file_ntcreate(conn, fname, &sbuf,
- FILE_WRITE_DATA,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- FORCE_OPLOCK_BREAK_TO_NONE,
- NULL);
-
- if (new_fsp == NULL) {
- if (open_was_deferred(SVAL(inbuf,smb_mid))) {
- /* We have re-scheduled this call. */
- return -1;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ /* 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:
+ {
+ status = smb_file_mode_information(conn,
+ pdata,
+ total_data);
+ break;
+ }
+
+ /*
+ * CIFS UNIX extensions.
+ */
+
+ case SMB_SET_FILE_UNIX_BASIC:
+ {
+ status = smb_set_file_unix_basic(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
+
+ case SMB_SET_FILE_UNIX_LINK:
+ {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
+ /* We must have a pathname for this. */
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- ret = vfs_set_filelen(new_fsp, size);
- close_file(new_fsp,NORMAL_CLOSE);
- } else {
- ret = vfs_set_filelen(fsp, size);
+ status = smb_set_file_unix_link(conn,
+ inbuf,
+ pdata,
+ total_data,
+ fname);
+ break;
}
- if (ret == -1) {
- return (UNIXERROR(ERRHRD,ERRdiskfull));
+ case SMB_SET_FILE_UNIX_HLINK:
+ {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
+ /* We must have a pathname for this. */
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+ status = smb_set_file_unix_hlink(conn,
+ inbuf,
+ outbuf,
+ pdata,
+ total_data,
+ fname);
+ break;
}
- }
- /*
- * Finally the times.
- */
- if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
- if(fsp != NULL) {
- /*
- * This was a setfileinfo on an open file.
- * NT does this a lot. We also need to
- * set the time here, as it can be read by
- * FindFirst/FindNext and with the patch for bug #2045
- * in smbd/fileio.c it ensures that this timestamp is
- * kept sticky even after a write. We save the request
- * away and will set it on file close and after a write. JRA.
- */
+ case SMB_FILE_RENAME_INFORMATION:
+ {
+ status = smb_file_rename_information(conn,
+ inbuf,
+ outbuf,
+ pdata,
+ total_data,
+ fsp,
+ fname);
+ break;
+ }
- if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
- DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
- fsp_set_pending_modtime(fsp, tvs.modtime);
+#if defined(HAVE_POSIX_ACLS)
+ case SMB_SET_POSIX_ACL:
+ {
+ status = smb_set_posix_acl(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
+#endif
+
+ case SMB_SET_POSIX_LOCK:
+ {
+ if (tran_call != TRANSACT2_SETFILEINFO) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+ status = smb_set_posix_lock(conn,
+ inbuf,
+ length,
+ pdata,
+ total_data,
+ fsp);
+ break;
+ }
+
+ case SMB_POSIX_PATH_OPEN:
+ {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
+ /* We must have a pathname for this. */
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
+ status = smb_posix_open(conn,
+ ppdata,
+ total_data,
+ fname,
+ &sbuf,
+ &data_return_size);
+ break;
+ }
+
+ case SMB_POSIX_PATH_UNLINK:
+ {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
+ /* We must have a pathname for this. */
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
+ status = smb_posix_unlink(conn,
+ pdata,
+ total_data,
+ fname,
+ &sbuf);
+ break;
}
- DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
- if(file_utime(conn, fname, &tvs)!=0) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ default:
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
+
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
+ if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
}
+ return ERROR_NT(status);
}
SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
- return(-1);
+ return -1;
}
/****************************************************************************
@@ -4751,30 +5543,27 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
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) {
+ if (total_params < 5) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ status = unix_convert(conn, directory, False, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/* Any data in this call is an EA list. */
@@ -4799,40 +5588,37 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
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);
+ ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
+ total_data - 4);
if (!ea_list) {
- talloc_destroy(ctx);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
} else if (IVAL(pdata,0) != 4) {
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);
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+ return ERROR_NT(status);
}
+ status = create_directory(conn, directory);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
/* Try and set any given EA. */
- if (total_data) {
+ if (ea_list) {
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 */
- *pparams = SMB_REALLOC(*pparams,2);
+ *pparams = (char *)SMB_REALLOC(*pparams,2);
if(*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -4840,7 +5626,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
SSVAL(params,0,0);
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -4874,7 +5660,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
}
/* Realloc the parameter and data sizes */
- *pparams = SMB_REALLOC(*pparams,6);
+ *pparams = (char *)SMB_REALLOC(*pparams,6);
if (*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -4889,7 +5675,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
if(fnf_handle == 0)
fnf_handle = 257;
- send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -4908,7 +5694,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char
DEBUG(3,("call_trans2findnotifynext\n"));
/* Realloc the parameter and data sizes */
- *pparams = SMB_REALLOC(*pparams,4);
+ *pparams = (char *)SMB_REALLOC(*pparams,4);
if (*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -4917,7 +5703,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char
SSVAL(params,0,0); /* No changes */
SSVAL(params,2,0); /* No EA errors */
- send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -4937,7 +5723,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
DEBUG(10,("call_trans2getdfsreferral\n"));
- if (total_params < 2) {
+ if (total_params < 3) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -4946,12 +5732,12 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
if(!lp_host_msdfs())
return ERROR_DOS(ERRDOS,ERRbadfunc);
- srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
+ srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
return UNIXERROR(ERRDOS,ERRbadfile);
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
- send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
+ send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
return(-1);
}
@@ -4977,7 +5763,7 @@ 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)) {
- *ppdata = SMB_REALLOC(*ppdata, 32);
+ *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
if (*ppdata == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -4989,7 +5775,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf,
SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
- send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
+ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
return(-1);
} else {
DEBUG(2,("Unknown TRANS2_IOCTL\n"));
@@ -5061,147 +5847,147 @@ int handle_trans2(connection_struct *conn,
switch(state->call) {
case TRANSACT2_OPEN:
{
- START_PROFILE_NESTED(Trans2_open);
+ START_PROFILE(Trans2_open);
outsize = call_trans2open(
conn, inbuf, outbuf, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_open);
+ END_PROFILE(Trans2_open);
break;
}
case TRANSACT2_FINDFIRST:
{
- START_PROFILE_NESTED(Trans2_findfirst);
+ START_PROFILE(Trans2_findfirst);
outsize = call_trans2findfirst(
conn, inbuf, outbuf, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_findfirst);
+ END_PROFILE(Trans2_findfirst);
break;
}
case TRANSACT2_FINDNEXT:
{
- START_PROFILE_NESTED(Trans2_findnext);
+ START_PROFILE(Trans2_findnext);
outsize = call_trans2findnext(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_findnext);
+ END_PROFILE(Trans2_findnext);
break;
}
case TRANSACT2_QFSINFO:
{
- START_PROFILE_NESTED(Trans2_qfsinfo);
+ START_PROFILE(Trans2_qfsinfo);
outsize = call_trans2qfsinfo(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_qfsinfo);
+ END_PROFILE(Trans2_qfsinfo);
break;
}
case TRANSACT2_SETFSINFO:
{
- START_PROFILE_NESTED(Trans2_setfsinfo);
+ START_PROFILE(Trans2_setfsinfo);
outsize = call_trans2setfsinfo(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_setfsinfo);
+ END_PROFILE(Trans2_setfsinfo);
break;
}
case TRANSACT2_QPATHINFO:
case TRANSACT2_QFILEINFO:
{
- START_PROFILE_NESTED(Trans2_qpathinfo);
+ START_PROFILE(Trans2_qpathinfo);
outsize = call_trans2qfilepathinfo(
conn, inbuf, outbuf, size, bufsize, state->call,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_qpathinfo);
+ END_PROFILE(Trans2_qpathinfo);
break;
}
case TRANSACT2_SETPATHINFO:
case TRANSACT2_SETFILEINFO:
{
- START_PROFILE_NESTED(Trans2_setpathinfo);
+ START_PROFILE(Trans2_setpathinfo);
outsize = call_trans2setfilepathinfo(
conn, inbuf, outbuf, size, bufsize, state->call,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_setpathinfo);
+ END_PROFILE(Trans2_setpathinfo);
break;
}
case TRANSACT2_FINDNOTIFYFIRST:
{
- START_PROFILE_NESTED(Trans2_findnotifyfirst);
+ START_PROFILE(Trans2_findnotifyfirst);
outsize = call_trans2findnotifyfirst(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_findnotifyfirst);
+ END_PROFILE(Trans2_findnotifyfirst);
break;
}
case TRANSACT2_FINDNOTIFYNEXT:
{
- START_PROFILE_NESTED(Trans2_findnotifynext);
+ START_PROFILE(Trans2_findnotifynext);
outsize = call_trans2findnotifynext(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_findnotifynext);
+ END_PROFILE(Trans2_findnotifynext);
break;
}
case TRANSACT2_MKDIR:
{
- START_PROFILE_NESTED(Trans2_mkdir);
+ START_PROFILE(Trans2_mkdir);
outsize = call_trans2mkdir(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_mkdir);
+ END_PROFILE(Trans2_mkdir);
break;
}
case TRANSACT2_GET_DFS_REFERRAL:
{
- START_PROFILE_NESTED(Trans2_get_dfs_referral);
+ START_PROFILE(Trans2_get_dfs_referral);
outsize = call_trans2getdfsreferral(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_get_dfs_referral);
+ END_PROFILE(Trans2_get_dfs_referral);
break;
}
case TRANSACT2_IOCTL:
{
- START_PROFILE_NESTED(Trans2_ioctl);
+ START_PROFILE(Trans2_ioctl);
outsize = call_trans2ioctl(
conn, inbuf, outbuf, size, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
- END_PROFILE_NESTED(Trans2_ioctl);
+ END_PROFILE(Trans2_ioctl);
break;
}
@@ -5246,7 +6032,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_DOS(ERRSRV,ERRaccess);
}
- if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
DEBUG(0, ("talloc failed\n"));
END_PROFILE(SMBtrans2);
return ERROR_NT(NT_STATUS_NO_MEMORY);
@@ -5257,6 +6043,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
state->mid = SVAL(inbuf, smb_mid);
state->vuid = SVAL(inbuf, smb_uid);
state->setup_count = SVAL(inbuf, smb_suwcnt);
+ state->setup = NULL;
state->total_param = SVAL(inbuf, smb_tpscnt);
state->param = NULL;
state->total_data = SVAL(inbuf, smb_tdscnt);
@@ -5299,7 +6086,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_data) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- state->data = SMB_MALLOC(state->total_data);
+ state->data = (char *)SMB_MALLOC(state->total_data);
if (state->data == NULL) {
DEBUG(0,("reply_trans2: data malloc fail for %u "
"bytes !\n", (unsigned int)state->total_data));
@@ -5319,7 +6106,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_param) {
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
- state->param = SMB_MALLOC(state->total_param);
+ state->param = (char *)SMB_MALLOC(state->total_param);
if (state->param == NULL) {
DEBUG(0,("reply_trans: param malloc fail for %u "
"bytes !\n", (unsigned int)state->total_param));
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index c62c9d928ab..85885803222 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -87,6 +87,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
unsigned int i;
struct vuid_cache_entry *ent = NULL;
BOOL readonly_share;
+ NT_USER_TOKEN *token;
for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
if (conn->vuid_cache.array[i].vuid == vuser->vuid) {
@@ -102,10 +103,14 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
vuser->nt_user_token,
- conn->service);
+ SNUM(conn));
+
+ token = conn->nt_user_token ?
+ conn->nt_user_token : vuser->nt_user_token;
if (!readonly_share &&
- !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
+ !share_access_check(token, lp_servicename(snum),
+ FILE_WRITE_DATA)) {
/* smb.conf allows r/w, but the security descriptor denies
* write. Fall back to looking at readonly. */
readonly_share = True;
@@ -113,7 +118,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
"security descriptor\n"));
}
- if (!share_access_check(conn, snum, vuser,
+ if (!share_access_check(token, lp_servicename(snum),
readonly_share ?
FILE_READ_DATA : FILE_WRITE_DATA)) {
return False;
@@ -129,7 +134,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
ent->admin_user = token_contains_name_in_list(
vuser->user.unix_name, NULL, vuser->nt_user_token,
- lp_admin_users(conn->service));
+ lp_admin_users(SNUM(conn)));
conn->read_only = ent->read_only;
conn->admin_user = ent->admin_user;
@@ -415,4 +420,3 @@ BOOL unbecome_user(void)
pop_conn_ctx();
return True;
}
-
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
deleted file mode 100644
index ee251c17d8d..00000000000
--- a/source/smbd/vfs-wrap.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Wrap disk only vfs functions to sidestep dodgy compilers.
- Copyright (C) Tim Potter 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_VFS
-
-
-/* Check for NULL pointer parameters in vfswrap_* functions */
-
-/* We don't want to have NULL function pointers lying around. Someone
- is sure to try and execute them. These stubs are used to prevent
- this possibility. */
-
-int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
-{
- return 0; /* Return >= 0 for success */
-}
-
-void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn)
-{
-}
-
-/* Disk operations */
-
-SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
- SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
-{
- SMB_BIG_UINT result;
-
- result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize);
- return result;
-}
-
-int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
- int result;
-
- START_PROFILE(syscall_get_quota);
- result = sys_get_quota(conn->connectpath, qtype, id, qt);
- END_PROFILE(syscall_get_quota);
- return result;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
- int result;
-
- START_PROFILE(syscall_set_quota);
- result = sys_set_quota(conn->connectpath, qtype, id, qt);
- END_PROFILE(syscall_set_quota);
- return result;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
-{
- errno = ENOSYS;
- return -1; /* Not implemented. */
-}
-
-int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf)
-{
- return sys_statvfs(path, statbuf);
-}
-
-/* Directory operations */
-
-SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
-{
- SMB_STRUCT_DIR *result;
-
- START_PROFILE(syscall_opendir);
- result = sys_opendir(fname);
- END_PROFILE(syscall_opendir);
- return result;
-}
-
-SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
- SMB_STRUCT_DIRENT *result;
-
- START_PROFILE(syscall_readdir);
- result = sys_readdir(dirp);
- END_PROFILE(syscall_readdir);
- return result;
-}
-
-void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp, long offset)
-{
- START_PROFILE(syscall_seekdir);
- sys_seekdir(dirp, offset);
- END_PROFILE(syscall_seekdir);
-}
-
-long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
- long result;
- START_PROFILE(syscall_telldir);
- result = sys_telldir(dirp);
- END_PROFILE(syscall_telldir);
- return result;
-}
-
-void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
- START_PROFILE(syscall_rewinddir);
- sys_rewinddir(dirp);
- END_PROFILE(syscall_rewinddir);
-}
-
-int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
-{
- int result;
- BOOL has_dacl = False;
-
- START_PROFILE(syscall_mkdir);
-
- if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
- mode = 0777;
-
- result = mkdir(path, mode);
-
- if (result == 0 && !has_dacl) {
- /*
- * We need to do this as the default behavior of POSIX ACLs
- * is to set the mask to be the requested group permission
- * bits, not the group permission bits to be the requested
- * group permission bits. This is not what we want, as it will
- * mess up any inherited ACL bits that were set. JRA.
- */
- int saved_errno = errno; /* We may get ENOSYS */
- if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS))
- errno = saved_errno;
- }
-
- END_PROFILE(syscall_mkdir);
- return result;
-}
-
-int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
- int result;
-
- START_PROFILE(syscall_rmdir);
- result = rmdir(path);
- END_PROFILE(syscall_rmdir);
- return result;
-}
-
-int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, SMB_STRUCT_DIR *dirp)
-{
- int result;
-
- START_PROFILE(syscall_closedir);
- result = sys_closedir(dirp);
- END_PROFILE(syscall_closedir);
- return result;
-}
-
-/* File operations */
-
-int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
-{
- int result;
-
- START_PROFILE(syscall_open);
- result = sys_open(fname, flags, mode);
- END_PROFILE(syscall_open);
- return result;
-}
-
-int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
- int result;
-
- START_PROFILE(syscall_close);
-
- result = close(fd);
- END_PROFILE(syscall_close);
- return result;
-}
-
-ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
-{
- ssize_t result;
-
- START_PROFILE_BYTES(syscall_read, n);
- result = sys_read(fd, data, n);
- END_PROFILE(syscall_read);
- return result;
-}
-
-ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data,
- size_t n, SMB_OFF_T offset)
-{
- ssize_t result;
-
-#if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
- START_PROFILE_BYTES(syscall_pread, n);
- result = sys_pread(fd, data, n, offset);
- END_PROFILE(syscall_pread);
-
- if (result == -1 && errno == ESPIPE) {
- /* Maintain the fiction that pipes can be seeked (sought?) on. */
- result = SMB_VFS_READ(fsp, fd, data, n);
- fsp->fh->pos = 0;
- }
-
-#else /* HAVE_PREAD */
- SMB_OFF_T curr;
- int lerrno;
-
- curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
- if (curr == -1 && errno == ESPIPE) {
- /* Maintain the fiction that pipes can be seeked (sought?) on. */
- result = SMB_VFS_READ(fsp, fd, data, n);
- fsp->fh->pos = 0;
- return result;
- }
-
- if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
- return -1;
- }
-
- errno = 0;
- result = SMB_VFS_READ(fsp, fd, data, n);
- lerrno = errno;
-
- SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
- errno = lerrno;
-
-#endif /* HAVE_PREAD */
-
- return result;
-}
-
-ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
-{
- ssize_t result;
-
- START_PROFILE_BYTES(syscall_write, n);
- result = sys_write(fd, data, n);
- END_PROFILE(syscall_write);
- return result;
-}
-
-ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data,
- size_t n, SMB_OFF_T offset)
-{
- ssize_t result;
-
-#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
- START_PROFILE_BYTES(syscall_pwrite, n);
- result = sys_pwrite(fd, data, n, offset);
- END_PROFILE(syscall_pwrite);
-
- if (result == -1 && errno == ESPIPE) {
- /* Maintain the fiction that pipes can be sought on. */
- result = SMB_VFS_WRITE(fsp, fd, data, n);
- }
-
-#else /* HAVE_PWRITE */
- SMB_OFF_T curr;
- int lerrno;
-
- curr = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
- if (curr == -1) {
- return -1;
- }
-
- if (SMB_VFS_LSEEK(fsp, fd, offset, SEEK_SET) == -1) {
- return -1;
- }
-
- result = SMB_VFS_WRITE(fsp, fd, data, n);
- lerrno = errno;
-
- SMB_VFS_LSEEK(fsp, fd, curr, SEEK_SET);
- errno = lerrno;
-
-#endif /* HAVE_PWRITE */
-
- return result;
-}
-
-SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
-{
- SMB_OFF_T result = 0;
-
- START_PROFILE(syscall_lseek);
-
- /* Cope with 'stat' file opens. */
- if (filedes != -1)
- result = sys_lseek(filedes, offset, whence);
-
- /*
- * We want to maintain the fiction that we can seek
- * on a fifo for file system purposes. This allows
- * people to set up UNIX fifo's that feed data to Windows
- * applications. JRA.
- */
-
- if((result == -1) && (errno == ESPIPE)) {
- result = 0;
- errno = 0;
- }
-
- END_PROFILE(syscall_lseek);
- return result;
-}
-
-ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
- SMB_OFF_T offset, size_t n)
-{
- ssize_t result;
-
- START_PROFILE_BYTES(syscall_sendfile, n);
- result = sys_sendfile(tofd, fromfd, hdr, offset, n);
- END_PROFILE(syscall_sendfile);
- return result;
-}
-
-/*********************************************************
- For rename across filesystems Patch from Warren Birnbaum
- <warrenb@hpcvscdp.cv.hp.com>
-**********************************************************/
-
-static int copy_reg(const char *source, const char *dest)
-{
- SMB_STRUCT_STAT source_stats;
- int saved_errno;
- int ifd = -1;
- int ofd = -1;
-
- if (sys_lstat (source, &source_stats) == -1)
- return -1;
-
- if (!S_ISREG (source_stats.st_mode))
- return -1;
-
- if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
- return -1;
-
- if (unlink (dest) && errno != ENOENT)
- return -1;
-
-#ifdef O_NOFOLLOW
- if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
-#else
- if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
-#endif
- goto err;
-
- if (transfer_file(ifd, ofd, (size_t)-1) == -1)
- goto err;
-
- /*
- * Try to preserve ownership. For non-root it might fail, but that's ok.
- * But root probably wants to know, e.g. if NFS disallows it.
- */
-
-#ifdef HAVE_FCHOWN
- if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
-#else
- if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
-#endif
- goto err;
-
- /*
- * fchown turns off set[ug]id bits for non-root,
- * so do the chmod last.
- */
-
-#if defined(HAVE_FCHMOD)
- if (fchmod (ofd, source_stats.st_mode & 07777))
-#else
- if (chmod (dest, source_stats.st_mode & 07777))
-#endif
- goto err;
-
- if (close (ifd) == -1)
- goto err;
-
- if (close (ofd) == -1)
- return -1;
-
- /* Try to copy the old file's modtime and access time. */
- {
- struct utimbuf tv;
-
- tv.actime = source_stats.st_atime;
- tv.modtime = source_stats.st_mtime;
- utime(dest, &tv);
- }
-
- if (unlink (source) == -1)
- return -1;
-
- return 0;
-
- err:
-
- saved_errno = errno;
- if (ifd != -1)
- close(ifd);
- if (ofd != -1)
- close(ofd);
- errno = saved_errno;
- return -1;
-}
-
-int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname)
-{
- int result;
-
- START_PROFILE(syscall_rename);
- result = rename(oldname, newname);
- if (errno == EXDEV) {
- /* Rename across filesystems needed. */
- result = copy_reg(oldname, newname);
- }
-
- END_PROFILE(syscall_rename);
- return result;
-}
-
-int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
-#ifdef HAVE_FSYNC
- int result;
-
- START_PROFILE(syscall_fsync);
- result = fsync(fd);
- END_PROFILE(syscall_fsync);
- return result;
-#else
- return 0;
-#endif
-}
-
-int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
-{
- int result;
-
- START_PROFILE(syscall_stat);
- result = sys_stat(fname, sbuf);
- END_PROFILE(syscall_stat);
- return result;
-}
-
-int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
-{
- int result;
-
- START_PROFILE(syscall_fstat);
- result = sys_fstat(fd, sbuf);
- END_PROFILE(syscall_fstat);
- return result;
-}
-
-int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
-{
- int result;
-
- START_PROFILE(syscall_lstat);
- result = sys_lstat(path, sbuf);
- END_PROFILE(syscall_lstat);
- return result;
-}
-
-int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
- int result;
-
- START_PROFILE(syscall_unlink);
- result = unlink(path);
- END_PROFILE(syscall_unlink);
- return result;
-}
-
-int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
-{
- int result;
-
- START_PROFILE(syscall_chmod);
-
- /*
- * We need to do this due to the fact that the default POSIX ACL
- * chmod modifies the ACL *mask* for the group owner, not the
- * group owner bits directly. JRA.
- */
-
-
- {
- int saved_errno = errno; /* We might get ENOSYS */
- if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) {
- END_PROFILE(syscall_chmod);
- return result;
- }
- /* Error - return the old errno. */
- errno = saved_errno;
- }
-
- result = chmod(path, mode);
- END_PROFILE(syscall_chmod);
- return result;
-}
-
-int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
-{
- int result;
-
- START_PROFILE(syscall_fchmod);
-
- /*
- * We need to do this due to the fact that the default POSIX ACL
- * chmod modifies the ACL *mask* for the group owner, not the
- * group owner bits directly. JRA.
- */
-
- {
- int saved_errno = errno; /* We might get ENOSYS */
- if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
- END_PROFILE(syscall_fchmod);
- return result;
- }
- /* Error - return the old errno. */
- errno = saved_errno;
- }
-
-#if defined(HAVE_FCHMOD)
- result = fchmod(fd, mode);
-#else
- result = -1;
- errno = ENOSYS;
-#endif
-
- END_PROFILE(syscall_fchmod);
- return result;
-}
-
-int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
-{
- int result;
-
- START_PROFILE(syscall_chown);
- result = sys_chown(path, uid, gid);
- END_PROFILE(syscall_chown);
- return result;
-}
-
-int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
-{
-#ifdef HAVE_FCHOWN
- int result;
-
- START_PROFILE(syscall_fchown);
- result = fchown(fd, uid, gid);
- END_PROFILE(syscall_fchown);
- return result;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
- int result;
-
- START_PROFILE(syscall_chdir);
- result = chdir(path);
- END_PROFILE(syscall_chdir);
- return result;
-}
-
-char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path)
-{
- char *result;
-
- START_PROFILE(syscall_getwd);
- result = sys_getwd(path);
- END_PROFILE(syscall_getwd);
- return result;
-}
-
-int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
-{
- int result;
-
- START_PROFILE(syscall_utime);
- result = utime(path, times);
- END_PROFILE(syscall_utime);
- return result;
-}
-
-/*********************************************************************
- A version of ftruncate that will write the space on disk if strict
- allocate is set.
-**********************************************************************/
-
-static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
-{
- SMB_STRUCT_STAT st;
- SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
- unsigned char zero_space[4096];
- SMB_OFF_T space_to_write;
-
- if (currpos == -1)
- return -1;
-
- if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
- return -1;
-
- space_to_write = len - st.st_size;
-
-#ifdef S_ISFIFO
- if (S_ISFIFO(st.st_mode))
- return 0;
-#endif
-
- if (st.st_size == len)
- return 0;
-
- /* Shrink - just ftruncate. */
- if (st.st_size > len)
- return sys_ftruncate(fd, len);
-
- /* Write out the real space on disk. */
- if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
- return -1;
-
- space_to_write = len - st.st_size;
-
- memset(zero_space, '\0', sizeof(zero_space));
- while ( space_to_write > 0) {
- SMB_OFF_T retlen;
- SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
-
- retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write);
- if (retlen <= 0)
- return -1;
-
- space_to_write -= retlen;
- }
-
- /* Seek to where we were */
- if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
- return -1;
-
- return 0;
-}
-
-int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
-{
- int result = -1;
- SMB_STRUCT_STAT st;
- char c = 0;
- SMB_OFF_T currpos;
-
- START_PROFILE(syscall_ftruncate);
-
- if (lp_strict_allocate(SNUM(fsp->conn))) {
- result = strict_allocate_ftruncate(handle, fsp, fd, len);
- END_PROFILE(syscall_ftruncate);
- return result;
- }
-
- /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
- sys_ftruncate if the system supports it. Then I discovered that
- you can have some filesystems that support ftruncate
- expansion and some that don't! On Linux fat can't do
- ftruncate extend but ext2 can. */
-
- result = sys_ftruncate(fd, len);
- if (result == 0)
- goto done;
-
- /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
- extend a file with ftruncate. Provide alternate implementation
- for this */
- currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
- if (currpos == -1) {
- goto done;
- }
-
- /* Do an fstat to see if the file is longer than the requested
- size in which case the ftruncate above should have
- succeeded or shorter, in which case seek to len - 1 and
- write 1 byte of zero */
- if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
- goto done;
- }
-
-#ifdef S_ISFIFO
- if (S_ISFIFO(st.st_mode)) {
- result = 0;
- goto done;
- }
-#endif
-
- if (st.st_size == len) {
- result = 0;
- goto done;
- }
-
- if (st.st_size > len) {
- /* the sys_ftruncate should have worked */
- goto done;
- }
-
- if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
- goto done;
-
- if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
- goto done;
-
- /* Seek to where we were */
- if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
- goto done;
- result = 0;
-
- done:
-
- END_PROFILE(syscall_ftruncate);
- return result;
-}
-
-BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
-{
- BOOL result;
-
- START_PROFILE(syscall_fcntl_lock);
- result = fcntl_lock(fd, op, offset, count, type);
- END_PROFILE(syscall_fcntl_lock);
- return result;
-}
-
-BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
-{
- BOOL result;
-
- START_PROFILE(syscall_fcntl_getlock);
- result = fcntl_getlock(fd, poffset, pcount, ptype, ppid);
- END_PROFILE(syscall_fcntl_getlock);
- return result;
-}
-
-int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
-{
- int result;
-
- START_PROFILE(syscall_symlink);
- result = sys_symlink(oldpath, newpath);
- END_PROFILE(syscall_symlink);
- return result;
-}
-
-int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
-{
- int result;
-
- START_PROFILE(syscall_readlink);
- result = sys_readlink(path, buf, bufsiz);
- END_PROFILE(syscall_readlink);
- return result;
-}
-
-int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
-{
- int result;
-
- START_PROFILE(syscall_link);
- result = sys_link(oldpath, newpath);
- END_PROFILE(syscall_link);
- return result;
-}
-
-int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
-{
- int result;
-
- START_PROFILE(syscall_mknod);
- result = sys_mknod(pathname, mode, dev);
- END_PROFILE(syscall_mknod);
- return result;
-}
-
-char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
-{
- char *result;
-
- START_PROFILE(syscall_realpath);
- result = sys_realpath(path, resolved_path);
- END_PROFILE(syscall_realpath);
- return result;
-}
-
-size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
-{
- size_t result;
-
- START_PROFILE(fget_nt_acl);
- result = get_nt_acl(fsp, security_info, ppdesc);
- END_PROFILE(fget_nt_acl);
- return result;
-}
-
-size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
-{
- size_t result;
-
- START_PROFILE(get_nt_acl);
- result = get_nt_acl(fsp, security_info, ppdesc);
- END_PROFILE(get_nt_acl);
- return result;
-}
-
-BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
-{
- BOOL result;
-
- START_PROFILE(fset_nt_acl);
- result = set_nt_acl(fsp, security_info_sent, psd);
- END_PROFILE(fset_nt_acl);
- return result;
-}
-
-BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
-{
- BOOL result;
-
- START_PROFILE(set_nt_acl);
- result = set_nt_acl(fsp, security_info_sent, psd);
- END_PROFILE(set_nt_acl);
- return result;
-}
-
-int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
-{
-#ifdef HAVE_NO_ACL
- errno = ENOSYS;
- return -1;
-#else
- int result;
-
- START_PROFILE(chmod_acl);
- result = chmod_acl(conn, name, mode);
- END_PROFILE(chmod_acl);
- return result;
-#endif
-}
-
-int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
-{
-#ifdef HAVE_NO_ACL
- errno = ENOSYS;
- return -1;
-#else
- int result;
-
- START_PROFILE(fchmod_acl);
- result = fchmod_acl(fsp, fd, mode);
- END_PROFILE(fchmod_acl);
- return result;
-#endif
-}
-
-int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
-{
- return sys_acl_get_entry(theacl, entry_id, entry_p);
-}
-
-int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
-{
- return sys_acl_get_tag_type(entry_d, tag_type_p);
-}
-
-int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
-{
- return sys_acl_get_permset(entry_d, permset_p);
-}
-
-void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
-{
- return sys_acl_get_qualifier(entry_d);
-}
-
-SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
-{
- return sys_acl_get_file(path_p, type);
-}
-
-SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
-{
- return sys_acl_get_fd(fd);
-}
-
-int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
-{
- return sys_acl_clear_perms(permset);
-}
-
-int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- return sys_acl_add_perm(permset, perm);
-}
-
-char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
-{
- return sys_acl_to_text(theacl, plen);
-}
-
-SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
-{
- return sys_acl_init(count);
-}
-
-int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
- return sys_acl_create_entry(pacl, pentry);
-}
-
-int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
-{
- return sys_acl_set_tag_type(entry, tagtype);
-}
-
-int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
-{
- return sys_acl_set_qualifier(entry, qual);
-}
-
-int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
-{
- return sys_acl_set_permset(entry, permset);
-}
-
-int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
-{
- return sys_acl_valid(theacl );
-}
-
-int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
-{
- return sys_acl_set_file(name, acltype, theacl);
-}
-
-int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
-{
- return sys_acl_set_fd(fd, theacl);
-}
-
-int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
-{
- return sys_acl_delete_def_file(path);
-}
-
-int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
-{
- return sys_acl_get_perm(permset, perm);
-}
-
-int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
-{
- return sys_acl_free_text(text);
-}
-
-int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
-{
- return sys_acl_free_acl(posix_acl);
-}
-
-int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
-{
- return sys_acl_free_qualifier(qualifier, tagtype);
-}
-
-/****************************************************************
- Extended attribute operations.
-*****************************************************************/
-
-ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
-{
- return sys_getxattr(path, name, value, size);
-}
-
-ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
-{
- return sys_lgetxattr(path, name, value, size);
-}
-
-ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
-{
- return sys_fgetxattr(fd, name, value, size);
-}
-
-ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
-{
- return sys_listxattr(path, list, size);
-}
-
-ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
-{
- return sys_llistxattr(path, list, size);
-}
-
-ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
-{
- return sys_flistxattr(fd, list, size);
-}
-
-int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
-{
- return sys_removexattr(path, name);
-}
-
-int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
-{
- return sys_lremovexattr(path, name);
-}
-
-int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
-{
- return sys_fremovexattr(fd, name);
-}
-
-int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
-{
- return sys_setxattr(path, name, value, size, flags);
-}
-
-int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
-{
- return sys_lsetxattr(path, name, value, size, flags);
-}
-
-int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
-{
- return sys_fsetxattr(fd, name, value, size, flags);
-}
-
-int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_read(aiocb);
-}
-
-int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_write(aiocb);
-}
-
-ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_return(aiocb);
-}
-
-int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_cancel(fd, aiocb);
-}
-
-int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_error(aiocb);
-}
-
-int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
-{
- return sys_aio_fsync(op, aiocb);
-}
-
-int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
-{
- return sys_aio_suspend(aiocb, n, timeout);
-}
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 2c9403a0790..82ea602187c 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -4,6 +4,7 @@
VFS initialisation and support functions
Copyright (C) Tim Potter 1999
Copyright (C) Alexander Bokovoy 2002
+ Copyright (C) James Peach 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,131 +38,6 @@ struct vfs_init_function_entry {
static struct vfs_init_function_entry *backends = NULL;
-/* Some structures to help us initialise the vfs operations table */
-
-struct vfs_syminfo {
- char *name;
- void *fptr;
-};
-
-/* Default vfs hooks. WARNING: The order of these initialisers is
- very important. They must be in the same order as defined in
- vfs.h. Change at your own peril. */
-
-static struct vfs_ops default_vfs = {
-
- {
- /* Disk operations */
-
- vfswrap_dummy_connect,
- vfswrap_dummy_disconnect,
- vfswrap_disk_free,
- vfswrap_get_quota,
- vfswrap_set_quota,
- vfswrap_get_shadow_copy_data,
- vfswrap_statvfs,
-
- /* Directory operations */
-
- vfswrap_opendir,
- vfswrap_readdir,
- vfswrap_seekdir,
- vfswrap_telldir,
- vfswrap_rewinddir,
- vfswrap_mkdir,
- vfswrap_rmdir,
- vfswrap_closedir,
-
- /* File operations */
-
- vfswrap_open,
- vfswrap_close,
- vfswrap_read,
- vfswrap_pread,
- vfswrap_write,
- vfswrap_pwrite,
- vfswrap_lseek,
- vfswrap_sendfile,
- vfswrap_rename,
- vfswrap_fsync,
- vfswrap_stat,
- vfswrap_fstat,
- vfswrap_lstat,
- vfswrap_unlink,
- vfswrap_chmod,
- vfswrap_fchmod,
- vfswrap_chown,
- vfswrap_fchown,
- vfswrap_chdir,
- vfswrap_getwd,
- vfswrap_utime,
- vfswrap_ftruncate,
- vfswrap_lock,
- vfswrap_getlock,
- vfswrap_symlink,
- vfswrap_readlink,
- vfswrap_link,
- vfswrap_mknod,
- vfswrap_realpath,
-
- /* Windows ACL operations. */
- vfswrap_fget_nt_acl,
- vfswrap_get_nt_acl,
- vfswrap_fset_nt_acl,
- vfswrap_set_nt_acl,
-
- /* POSIX ACL operations. */
- vfswrap_chmod_acl,
- vfswrap_fchmod_acl,
-
- vfswrap_sys_acl_get_entry,
- vfswrap_sys_acl_get_tag_type,
- vfswrap_sys_acl_get_permset,
- vfswrap_sys_acl_get_qualifier,
- vfswrap_sys_acl_get_file,
- vfswrap_sys_acl_get_fd,
- vfswrap_sys_acl_clear_perms,
- vfswrap_sys_acl_add_perm,
- vfswrap_sys_acl_to_text,
- vfswrap_sys_acl_init,
- vfswrap_sys_acl_create_entry,
- vfswrap_sys_acl_set_tag_type,
- vfswrap_sys_acl_set_qualifier,
- vfswrap_sys_acl_set_permset,
- vfswrap_sys_acl_valid,
- vfswrap_sys_acl_set_file,
- vfswrap_sys_acl_set_fd,
- vfswrap_sys_acl_delete_def_file,
- vfswrap_sys_acl_get_perm,
- vfswrap_sys_acl_free_text,
- vfswrap_sys_acl_free_acl,
- vfswrap_sys_acl_free_qualifier,
-
- /* EA operations. */
- vfswrap_getxattr,
- vfswrap_lgetxattr,
- vfswrap_fgetxattr,
- vfswrap_listxattr,
- vfswrap_llistxattr,
- vfswrap_flistxattr,
- vfswrap_removexattr,
- vfswrap_lremovexattr,
- vfswrap_fremovexattr,
- vfswrap_setxattr,
- vfswrap_lsetxattr,
- vfswrap_fsetxattr,
-
- /* AIO operations. */
- vfswrap_aio_read,
- vfswrap_aio_write,
- vfswrap_aio_return,
- vfswrap_aio_cancel,
- vfswrap_aio_error,
- vfswrap_aio_fsync,
- vfswrap_aio_suspend
- }
-};
-
/****************************************************************************
maintain the list of available backends
****************************************************************************/
@@ -217,15 +93,20 @@ NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tu
static void vfs_init_default(connection_struct *conn)
{
DEBUG(3, ("Initialising default vfs hooks\n"));
-
- memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops));
- memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops));
+ vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
}
/****************************************************************************
initialise custom vfs hooks
****************************************************************************/
+static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which,
+ struct vfs_handle_struct * handle, void * op)
+{
+ ((struct vfs_handle_struct **)&vfs->handles)[which] = handle;
+ ((void **)(void *)&vfs->ops)[which] = op;
+}
+
BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
{
vfs_op_tuple *ops;
@@ -292,18 +173,15 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
for(i=0; ops[i].op != NULL; i++) {
DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
- /* Check whether this operation was already made opaque by different module */
- if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) {
- /* No, it isn't overloaded yet. Overload. */
- DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
- ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op;
- ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle;
- }
+ /* If this operation was already made opaque by different module, it
+ * will be overridded here.
+ */
+ DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
+ vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op);
}
/* Change current VFS disposition*/
DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
- ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op;
- ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle;
+ vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op);
}
SAFE_FREE(module_name);
@@ -311,6 +189,71 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
}
/*****************************************************************
+ Allow VFS modules to extend files_struct with VFS-specific state.
+ This will be ok for small numbers of extensions, but might need to
+ be refactored if it becomes more widely used.
+******************************************************************/
+
+#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
+
+void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size)
+{
+ struct vfs_fsp_data *ext;
+ void * ext_data;
+
+ /* Prevent VFS modules adding multiple extensions. */
+ if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
+ return ext_data;
+ }
+
+ ext = (struct vfs_fsp_data *)TALLOC_ZERO(
+ handle->conn->mem_ctx, sizeof(struct vfs_fsp_data) + ext_size);
+ if (ext == NULL) {
+ return NULL;
+ }
+
+ ext->owner = handle;
+ ext->next = fsp->vfs_extension;
+ fsp->vfs_extension = ext;
+ return EXT_DATA_AREA(ext);
+}
+
+void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
+{
+ struct vfs_fsp_data *curr;
+ struct vfs_fsp_data *prev;
+
+ for (curr = fsp->vfs_extension, prev = NULL;
+ curr;
+ prev = curr, curr = curr->next) {
+ if (curr->owner == handle) {
+ if (prev) {
+ prev->next = curr->next;
+ } else {
+ fsp->vfs_extension = curr->next;
+ }
+ TALLOC_FREE(curr);
+ return;
+ }
+ }
+}
+
+void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
+{
+ struct vfs_fsp_data *head;
+
+ for (head = fsp->vfs_extension; head; head = head->next) {
+ if (head->owner == handle) {
+ return EXT_DATA_AREA(head);
+ }
+ }
+
+ return NULL;
+}
+
+#undef EXT_DATA_AREA
+
+/*****************************************************************
Generic VFS init.
******************************************************************/
@@ -364,31 +307,6 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_
}
/*******************************************************************
- vfs mkdir wrapper
-********************************************************************/
-
-int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode)
-{
- int ret;
- SMB_STRUCT_STAT sbuf;
-
- if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) {
-
- inherit_access_acl(conn, name, mode);
-
- /*
- * Check if high bits should have been set,
- * then (if bits are missing): add them.
- * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir.
- */
- if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) &&
- !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode))
- SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode));
- }
- return ret;
-}
-
-/*******************************************************************
Check if an object exists in the vfs.
********************************************************************/
@@ -536,6 +454,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
if (((SMB_OFF_T)len) < 0) {
DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name ));
+ errno = EINVAL;
return -1;
}
@@ -595,8 +514,13 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
release_level_2_oplocks_on_change(fsp);
DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
- if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1)
+ if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1) {
set_filelen_write_cache(fsp, len);
+ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES,
+ fsp->fsp_name);
+ }
return ret;
}
@@ -704,7 +628,7 @@ char *vfs_readdirname(connection_struct *conn, void *p)
if (!p)
return(NULL);
- ptr = SMB_VFS_READDIR(conn,p);
+ ptr = SMB_VFS_READDIR(conn, (DIR *)p);
if (!ptr)
return(NULL);
@@ -873,37 +797,12 @@ char *vfs_GetWd(connection_struct *conn, char *path)
return (path);
}
-BOOL canonicalize_path(connection_struct *conn, pstring path)
-{
-#ifdef REALPATH_TAKES_NULL
- char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
- if (!resolved_name) {
- return False;
- }
- pstrcpy(path, resolved_name);
- SAFE_FREE(resolved_name);
- return True;
-#else
-#ifdef PATH_MAX
- char resolved_name_buf[PATH_MAX+1];
-#else
- pstring resolved_name_buf;
-#endif
- char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
- if (!resolved_name) {
- return False;
- }
- pstrcpy(path, resolved_name);
- return True;
-#endif /* REALPATH_TAKES_NULL */
-}
-
/*******************************************************************
Reduce a file name, removing .. elements and checking that
it is below dir in the heirachy. This uses realpath.
********************************************************************/
-BOOL reduce_name(connection_struct *conn, const pstring fname)
+NTSTATUS reduce_name(connection_struct *conn, const pstring fname)
{
#ifdef REALPATH_TAKES_NULL
BOOL free_resolved_name = True;
@@ -918,7 +817,6 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
char *resolved_name = NULL;
size_t con_path_len = strlen(conn->connectpath);
char *p = NULL;
- int saved_errno = errno;
DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
@@ -932,8 +830,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
switch (errno) {
case ENOTDIR:
DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
- errno = saved_errno;
- return False;
+ return map_nt_error_from_unix(errno);
case ENOENT:
{
pstring tmp_fname;
@@ -957,8 +854,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
#endif
if (!resolved_name) {
DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
- errno = saved_errno;
- return False;
+ return map_nt_error_from_unix(errno);
}
pstrcpy(tmp_fname, resolved_name);
pstrcat(tmp_fname, "/");
@@ -968,8 +864,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
resolved_name = SMB_STRDUP(tmp_fname);
if (!resolved_name) {
DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
- errno = saved_errno;
- return False;
+ return NT_STATUS_NO_MEMORY;
}
#else
#ifdef PATH_MAX
@@ -983,9 +878,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
}
default:
DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
- /* Don't restore the saved errno. We need to return the error that
- realpath caused here as it was not one of the cases we handle. JRA. */
- return False;
+ return map_nt_error_from_unix(errno);
}
}
@@ -993,19 +886,19 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
if (*resolved_name != '/') {
DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
- if (free_resolved_name)
+ if (free_resolved_name) {
SAFE_FREE(resolved_name);
- errno = saved_errno;
- return False;
+ }
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
/* Check for widelinks allowed. */
if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
- if (free_resolved_name)
+ if (free_resolved_name) {
SAFE_FREE(resolved_name);
- errno = EACCES;
- return False;
+ }
+ return NT_STATUS_ACCESS_DENIED;
}
/* Check if we are allowing users to follow symlinks */
@@ -1017,18 +910,18 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
SMB_STRUCT_STAT statbuf;
if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
(S_ISLNK(statbuf.st_mode)) ) {
- if (free_resolved_name)
+ if (free_resolved_name) {
SAFE_FREE(resolved_name);
+ }
DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
- errno = EACCES;
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
}
#endif
DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
- if (free_resolved_name)
+ if (free_resolved_name) {
SAFE_FREE(resolved_name);
- errno = saved_errno;
- return(True);
+ }
+ return NT_STATUS_OK;
}
diff --git a/source/smbwrapper/PORTING b/source/smbwrapper/PORTING
deleted file mode 100644
index 884246d078a..00000000000
--- a/source/smbwrapper/PORTING
+++ /dev/null
@@ -1,77 +0,0 @@
-This describes how to port the smbwrapper portion of Samba to a new
-unix-like platform. Note that porting smbwrapper is considerably
-harder than porting Samba, for Samba you generally just need to run
-configure and recompile whereas for smbwrapper some extra effort is
-generally required.
-
-
-STEP 1
-------
-
-The first step is to work out how to create a shared library on your
-OS and how to compile C code to produce position independent object
-files (PIC files). You shoud be able to find this information in the
-man pages for your compiler and loader (ld). Then modify configure.in
-to give that information to Samba.
-
-
-STEP 2
-------
-
-The next step is to work out how to preload shared objects. On many
-systems this is done using a LD_PRELOAD environment variable. On
-others (shc as IRIX) it may use a _RTL_LIST variable.
-
-To make sure it works I suggest you create two C files like this:
-
-/* first C file */
-main()
-{
- unlink("foo.txt");
-}
-
-/* second C file */
-#include <stdio.h>
-
-int unlink(char *fname)
-{
- fprintf(stderr,"unlink(%s) called\n",fname);
-}
-
-
-then compile the first as an ordinary C program and the second as a
-shared library. Then use LD_PRELOAD to preload the resulting shared
-library. Then run the first program. It should print "unlink(foo.txt)
-called". If it doesn't then consult your man pages till you get it
-right.
-
-Once you work this out then edit smbwrapper/smbsh.in and add a section
-if necessary to correctly set the necessary preload options for your
-OS.
-
-
-STEP 3
-------
-
-The next step is to work out how to make direct system calls. On most
-machines this will work without any source code changes to
-smbwrapper. To test that it does work create the following C program:
-
-#include <sys/syscall.h>
-main()
-{
- syscall(SYS_write, 1, "hello world\n", 12);
-}
-
-and try to compile/run it. If it produces "hello world" then syscall()
-works as expected. If not then work out what needs to be changed and
-then make that change in realcalls.h. For example, on IRIX 6.4 the
-system call numbers are wrong and need to be fixed up by getting an
-offset right.
-
-
-STEP 4
-------
-
-Try compiling smbwrapper! Then test it. Then debug it. Simple really :)
-
diff --git a/source/smbwrapper/README b/source/smbwrapper/README
deleted file mode 100644
index 8d5c376f825..00000000000
--- a/source/smbwrapper/README
+++ /dev/null
@@ -1,94 +0,0 @@
-This is a prelodable shared library that provides SMB client services
-for existing executables. Using this you can simulate a smb
-filesystem.
-
-*** This is code under development. Some things don't work yet ***
-
-Currently this code has been tested on:
-
-- Linux 2.0 with glibc2 (RH5.1)
-- Linux 2.1 with glibc2
-- Solaris 2.5.1 with gcc
-- Solaris 2.6 with gcc
-- SunOS 4.1.3 with gcc
-- IRIX 6.4 with cc
-- OSF1 with gcc
-
-
-It probably won't run on other systems without some porting. If you
-have a different system then see the file PORTING.
-
-To use it you need to do this:
-
-1) build smbwrapper.so using the command "make smbwrapper"
-3) run smbsh
-
-You will be asked for a username and password. After that you will be
-returned to a shell prompt. It is actually a subshell running with
-smbwrapper enabled.
-
-Now try to access /smb/SERVER for some SMB server name and see what
-happens. If you use the -W option to set your workgroup or have
-workgroup set in your smb.conf then listing /smb/ should list all SMB
-servers in your workgroup.
-
-
-OPTIONS
--------
-
--U username
- specify the username and optional password (as user%password)
-
--d debug level
- This is an integer that controls the internal debug level of smbw. It
- defaults to 0, which means no debug info.
-
--l logfile
- The place where smbw debug logs are put. If this is not set then
- stderr is used.
-
--P prefix
- The root of the SMB filesystem. This defaults to /smb/ but you can
- set it to any name you like.
-
--W workgroup
- This is the workgroup used for browsing (ie. listing machines in the
- /smb/ directory). It defaults to the one set in smb.conf.
-
--R resolve order
- This allows you to override the setting of the name resolve order
- from smb.conf
-
-
-ATTRIBUTE MAPPING
------------------
-
-smbwrapper does an inverse attribute maping to what Samba does. This
-means that the archive bit appears as the user execute bit, the system
-bit appears as the group execute bit and the hidden bit appears as the
-other execute bit. You can control these with chmod. The mapping can
-be enabled an disabled using the normal smb.conf controls (ie. "map
-archive", "map system" and "map hidden").
-
-Read-only files appear as non-writeable by everyone. Writeable files
-appear as writeable by the current user.
-
-
-WHAT WORKS
-----------
-
-Things that I have tried and do seem to work include:
-
- emacs, tar, ls, cmp, cp, rsync, du, cat, rm, mv, less, more, wc, head,
- tail, bash, tcsh, mkdir, rmdir, vim, xedit, diff
-
-things that I know don't work:
-
- anything executing from the share
- anything that uses mmap
- redirection within shells to smbsh files
-
-If you want to help with the development of this code then join the
-samba-technical mailing list.
-
-
diff --git a/source/smbwrapper/realcalls.h b/source/smbwrapper/realcalls.h
deleted file mode 100644
index bad89d598c1..00000000000
--- a/source/smbwrapper/realcalls.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- defintions of syscall entries
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#if HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#elif HAVE_SYSCALL_H
-#include <syscall.h>
-#endif
-
-#ifdef IRIX
-/* amazingly, IRIX gets its own syscall numbers wrong! */
-#ifdef SYSVoffset
-#if (SYSVoffset == 1)
-#undef SYSVoffset
-#define SYSVoffset 1000
-#endif
-#endif
-#endif
-
-/* this file is partly derived from zlibc by Alain Knaff */
-
-#define real_access(fn, mode) (syscall(SYS_access, (fn), (mode)))
-#define real_chdir(fn) (syscall(SYS_chdir, (fn)))
-#define real_chmod(fn, mode) (syscall(SYS_chmod,(fn), (mode)))
-#define real_chown(fn, owner, group) (syscall(SYS_chown,(fn),(owner),(group)))
-
-#ifdef SYS_getdents
-#define real_getdents(fd, dirp, count) (syscall(SYS_getdents, (fd), (dirp), (count)))
-#endif
-
-#define real_link(fn1, fn2) (syscall(SYS_link, (fn1), (fn2)))
-
-#define real_open(fn,flags,mode) (syscall(SYS_open, (fn), (flags), (mode)))
-
-#ifdef SYS_open64
-#define real_open64(fn,flags,mode) (syscall(SYS_open64, (fn), (flags), (mode)))
-#elif HAVE__OPEN64
-#define real_open64(fn,flags,mode) (_open64(fn,flags,mode))
-#define NO_OPEN64_ALIAS
-#elif HAVE___OPEN64
-#define real_open64(fn,flags,mode) (__open64(fn,flags,mode))
-#define NO_OPEN64_ALIAS
-#endif
-
-#ifdef HAVE__FORK
-#define real_fork() (_fork())
-#elif HAVE___FORK
-#define real_fork() (__fork())
-#elif SYS_fork
-#define real_fork() (syscall(SYS_fork))
-#endif
-
-#ifdef HAVE__OPENDIR
-#define real_opendir(fn) (_opendir(fn))
-#elif SYS_opendir
-#define real_opendir(fn) (syscall(SYS_opendir,(fn)))
-#elif HAVE___OPENDIR
-#define real_opendir(fn) (__opendir(fn))
-#endif
-
-#ifdef HAVE__READDIR
-#define real_readdir(d) (_readdir(d))
-#elif HAVE___READDIR
-#define real_readdir(d) (__readdir(d))
-#elif SYS_readdir
-#define real_readdir(d) (syscall(SYS_readdir,(d)))
-#endif
-
-#ifdef HAVE__CLOSEDIR
-#define real_closedir(d) (_closedir(d))
-#elif SYS_closedir
-#define real_closedir(d) (syscall(SYS_closedir,(d)))
-#elif HAVE___CLOSEDIR
-#define real_closedir(d) (__closedir(d))
-#endif
-
-#ifdef HAVE__SEEKDIR
-#define real_seekdir(d,l) (_seekdir(d,l))
-#elif SYS_seekdir
-#define real_seekdir(d,l) (syscall(SYS_seekdir,(d),(l)))
-#elif HAVE___SEEKDIR
-#define real_seekdir(d,l) (__seekdir(d,l))
-#else
-#define NO_SEEKDIR_WRAPPER
-#endif
-
-#ifdef HAVE__TELLDIR
-#define real_telldir(d) (_telldir(d))
-#elif SYS_telldir
-#define real_telldir(d) (syscall(SYS_telldir,(d)))
-#elif HAVE___TELLDIR
-#define real_telldir(d) (__telldir(d))
-#endif
-
-#ifdef HAVE__DUP
-#define real_dup(d) (_dup(d))
-#elif SYS_dup
-#define real_dup(d) (syscall(SYS_dup,(d)))
-#elif HAVE___DUP
-#define real_dup(d) (__dup(d))
-#endif
-
-#ifdef HAVE__DUP2
-#define real_dup2(d1,d2) (_dup2(d1,d2))
-#elif SYS_dup2
-#define real_dup2(d1,d2) (syscall(SYS_dup2,(d1),(d2)))
-#elif HAVE___DUP2
-#define real_dup2(d1,d2) (__dup2(d1,d2))
-#endif
-
-#ifdef HAVE__GETCWD
-#define real_getcwd(b,s) ((char *)_getcwd(b,s))
-#elif SYS_getcwd
-#define real_getcwd(b,s) ((char *)syscall(SYS_getcwd,(b),(s)))
-#elif HAVE___GETCWD
-#define real_getcwd(b,s) ((char *)__getcwd(b,s))
-#endif
-
-#ifdef HAVE__STAT
-#define real_stat(fn,st) (_stat(fn,st))
-#elif SYS_stat
-#define real_stat(fn,st) (syscall(SYS_stat,(fn),(st)))
-#elif HAVE___STAT
-#define real_stat(fn,st) (__stat(fn,st))
-#endif
-
-#ifdef HAVE__LSTAT
-#define real_lstat(fn,st) (_lstat(fn,st))
-#elif SYS_lstat
-#define real_lstat(fn,st) (syscall(SYS_lstat,(fn),(st)))
-#elif HAVE___LSTAT
-#define real_lstat(fn,st) (__lstat(fn,st))
-#endif
-
-#ifdef HAVE__FSTAT
-#define real_fstat(fd,st) (_fstat(fd,st))
-#elif SYS_fstat
-#define real_fstat(fd,st) (syscall(SYS_fstat,(fd),(st)))
-#elif HAVE___FSTAT
-#define real_fstat(fd,st) (__fstat(fd,st))
-#endif
-
-#if defined(HAVE_SYS_ACL_H) && defined(HAVE__ACL)
-#define real_acl(fn,cmd,n,buf) (_acl(fn,cmd,n,buf))
-#elif SYS_acl
-#define real_acl(fn,cmd,n,buf) (syscall(SYS_acl,(fn),(cmd),(n),(buf)))
-#elif HAVE___ACL
-#define real_acl(fn,cmd,n,buf) (__acl(fn,cmd,n,buf))
-#else
-#define NO_ACL_WRAPPER
-#endif
-
-#ifdef HAVE__FACL
-#define real_facl(fd,cmd,n,buf) (_facl(fd,cmd,n,buf))
-#elif SYS_facl
-#define real_facl(fd,cmd,n,buf) (syscall(SYS_facl,(fd),(cmd),(n),(buf)))
-#elif HAVE___FACL
-#define real_facl(fd,cmd,n,buf) (__facl(fd,cmd,n,buf))
-#else
-#define NO_FACL_WRAPPER
-#endif
-
-
-#ifdef HAVE__STAT64
-#define real_stat64(fn,st) (_stat64(fn,st))
-#elif HAVE___STAT64
-#define real_stat64(fn,st) (__stat64(fn,st))
-#endif
-
-#ifdef HAVE__LSTAT64
-#define real_lstat64(fn,st) (_lstat64(fn,st))
-#elif HAVE___LSTAT64
-#define real_lstat64(fn,st) (__lstat64(fn,st))
-#endif
-
-#ifdef HAVE__FSTAT64
-#define real_fstat64(fd,st) (_fstat64(fd,st))
-#elif HAVE___FSTAT64
-#define real_fstat64(fd,st) (__fstat64(fd,st))
-#endif
-
-#ifdef HAVE__READDIR64
-#define real_readdir64(d) (_readdir64(d))
-#elif HAVE___READDIR64
-#define real_readdir64(d) (__readdir64(d))
-#endif
-
-#ifdef HAVE__LLSEEK
-#define real_llseek(fd,ofs,whence) (_llseek(fd,ofs,whence))
-#elif HAVE___LLSEEK
-#define real_llseek(fd,ofs,whence) (__llseek(fd,ofs,whence))
-#elif HAVE___SYS_LLSEEK
-#define real_llseek(fd,ofs,whence) (__sys_llseek(fd,ofs,whence))
-#endif
-
-
-#ifdef HAVE__PREAD
-#define real_pread(fd,buf,size,ofs) (_pread(fd,buf,size,ofs))
-#elif HAVE___PREAD
-#define real_pread(fd,buf,size,ofs) (__pread(fd,buf,size,ofs))
-#endif
-
-#ifdef HAVE__PREAD64
-#define real_pread64(fd,buf,size,ofs) (_pread64(fd,buf,size,ofs))
-#elif HAVE___PREAD64
-#define real_pread64(fd,buf,size,ofs) (__pread64(fd,buf,size,ofs))
-#endif
-
-#ifdef HAVE__PWRITE
-#define real_pwrite(fd,buf,size,ofs) (_pwrite(fd,buf,size,ofs))
-#elif HAVE___PWRITE
-#define real_pwrite(fd,buf,size,ofs) (__pwrite(fd,buf,size,ofs))
-#endif
-
-#ifdef HAVE__PWRITE64
-#define real_pwrite64(fd,buf,size,ofs) (_pwrite64(fd,buf,size,ofs))
-#elif HAVE___PWRITE64
-#define real_pwrite64(fd,buf,size,ofs) (__pwrite64(fd,buf,size,ofs))
-#endif
-
-
-#define real_readlink(fn,buf,len) (syscall(SYS_readlink, (fn), (buf), (len)))
-#define real_rename(fn1, fn2) (syscall(SYS_rename, (fn1), (fn2)))
-#define real_symlink(fn1, fn2) (syscall(SYS_symlink, (fn1), (fn2)))
-#define real_read(fd, buf, count ) (syscall(SYS_read, (fd), (buf), (count)))
-#define real_lseek(fd, offset, whence) (syscall(SYS_lseek, (fd), (offset), (whence)))
-#define real_write(fd, buf, count ) (syscall(SYS_write, (fd), (buf), (count)))
-#define real_close(fd) (syscall(SYS_close, (fd)))
-#define real_fchdir(fd) (syscall(SYS_fchdir, (fd)))
-#define real_fcntl(fd,cmd,arg) (syscall(SYS_fcntl, (fd), (cmd), (arg)))
-#define real_symlink(fn1, fn2) (syscall(SYS_symlink, (fn1), (fn2)))
-#define real_unlink(fn) (syscall(SYS_unlink, (fn)))
-#define real_rmdir(fn) (syscall(SYS_rmdir, (fn)))
-#define real_mkdir(fn, mode) (syscall(SYS_mkdir, (fn), (mode)))
-
-/*
- * On GNU/Linux distributions which allow to use both 2.4 and 2.6 kernels
- * there is SYS_utimes syscall defined at compile time in glibc-kernheaders but
- * it is available on 2.6 kernels only. Therefore, we can't rely on syscall at
- * compile time but have to check that behaviour during program execution. An easy
- * workaround is to have replacement for utimes() implemented within our wrapper and
- * do not rely on syscall at all. Thus, if REPLACE_UTIME is defined already (by packager),
- * skip these syscall shortcuts.
- */
-#ifndef REPLACE_UTIME
-#ifdef SYS_utime
-#define real_utime(fn, buf) (syscall(SYS_utime, (fn), (buf)))
-#else
-#define REPLACE_UTIME 1
-#endif
-#endif
-
-#ifndef REPLACE_UTIMES
-#ifdef SYS_utimes
-#define real_utimes(fn, buf) (syscall(SYS_utimes, (fn), (buf)))
-#else
-#define REPLACE_UTIMES 1
-#endif
-#endif
diff --git a/source/smbwrapper/shared.c b/source/smbwrapper/shared.c
deleted file mode 100644
index c7f1951f8bb..00000000000
--- a/source/smbwrapper/shared.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper functions - shared variables
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-static int shared_fd;
-static char *variables;
-static int shared_size;
-
-/*****************************************************
-setup the shared area
-*******************************************************/
-void smbw_setup_shared(void)
-{
- int fd;
- pstring name, s;
-
- slprintf(name,sizeof(name)-1, "%s/smbw.XXXXXX",tmpdir());
-
- fd = smb_mkstemp(name);
-
- if (fd == -1) goto failed;
-
- unlink(name);
-
- shared_fd = set_maxfiles(SMBW_MAX_OPEN);
-
- while (shared_fd && dup2(fd, shared_fd) != shared_fd) shared_fd--;
-
- if (shared_fd == 0) goto failed;
-
- close(fd);
-
- DEBUG(4,("created shared_fd=%d\n", shared_fd));
-
- slprintf(s,sizeof(s)-1,"%d", shared_fd);
-
- setenv("SMBW_HANDLE", s, 1);
-
- return;
-
- failed:
- perror("Failed to setup shared variable area ");
- exit(1);
-}
-
-static int locked;
-
-/*****************************************************
-lock the shared variable area
-*******************************************************/
-static void lockit(void)
-{
- if (shared_fd == 0) {
- char *p = getenv("SMBW_HANDLE");
- if (!p) {
- DEBUG(0,("ERROR: can't get smbw shared handle\n"));
- exit(1);
- }
- shared_fd = atoi(p);
- }
- if (locked==0 &&
- fcntl_lock(shared_fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
- DEBUG(0,("ERROR: can't get smbw shared lock (%s)\n", strerror(errno)));
- exit(1);
- }
- locked++;
-}
-
-/*****************************************************
-unlock the shared variable area
-*******************************************************/
-static void unlockit(void)
-{
- locked--;
- if (locked == 0) {
- fcntl_lock(shared_fd,SMB_F_SETLK,0,1,F_UNLCK);
- }
-}
-
-
-/*****************************************************
-get a variable from the shared area
-*******************************************************/
-char *smbw_getshared(const char *name)
-{
- int i;
- struct stat st;
- char *var;
-
- lockit();
-
- /* maybe the area has changed */
- if (fstat(shared_fd, &st)) goto failed;
-
- if (st.st_size != shared_size) {
- var = (char *)Realloc(variables, st.st_size, True);
- if (!var) goto failed;
- else variables = var;
- shared_size = st.st_size;
- lseek(shared_fd, 0, SEEK_SET);
- if (read(shared_fd, variables, shared_size) != shared_size) {
- goto failed;
- }
- }
-
- unlockit();
-
- i=0;
- while (i < shared_size) {
- char *n, *v;
- int l1, l2;
-
- l1 = SVAL(&variables[i], 0);
- l2 = SVAL(&variables[i], 2);
-
- n = &variables[i+4];
- v = &variables[i+4+l1];
- i += 4+l1+l2;
-
- if (strcmp(name,n)) {
- continue;
- }
- return v;
- }
-
- return NULL;
-
- failed:
- DEBUG(0,("smbw: shared variables corrupt (%s)\n", strerror(errno)));
- exit(1);
- return NULL;
-}
-
-
-
-/*****************************************************
-set a variable in the shared area
-*******************************************************/
-void smbw_setshared(const char *name, const char *val)
-{
- int l1, l2;
- char *var;
-
- /* we don't allow variable overwrite */
- if (smbw_getshared(name)) return;
-
- lockit();
-
- l1 = strlen(name)+1;
- l2 = strlen(val)+1;
-
- var = (char *)Realloc(variables, shared_size + l1+l2+4, True);
-
- if (!var) {
- DEBUG(0,("out of memory in smbw_setshared\n"));
- exit(1);
- }
-
- variables = var;
-
- SSVAL(&variables[shared_size], 0, l1);
- SSVAL(&variables[shared_size], 2, l2);
-
- safe_strcpy(&variables[shared_size] + 4, name, l1-1);
- safe_strcpy(&variables[shared_size] + 4 + l1, val, l2-1);
-
- shared_size += l1+l2+4;
-
- lseek(shared_fd, 0, SEEK_SET);
- if (write(shared_fd, variables, shared_size) != shared_size) {
- DEBUG(0,("smbw_setshared failed (%s)\n", strerror(errno)));
- exit(1);
- }
-
- unlockit();
-}
-
-
-/*****************************************************************
-return true if the passed fd is the SMBW_HANDLE
-*****************************************************************/
-int smbw_shared_fd(int fd)
-{
- return (shared_fd && shared_fd == fd);
-}
diff --git a/source/smbwrapper/smbsh.c b/source/smbwrapper/smbsh.c
deleted file mode 100644
index 8c9d971bbe2..00000000000
--- a/source/smbwrapper/smbsh.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper functions - frontend
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-static void smbsh_usage(void)
-{
- printf("smbsh [options]\n\n");
- printf(" -W workgroup\n");
- printf(" -U username\n");
- printf(" -P prefix\n");
- printf(" -R resolve order\n");
- printf(" -d debug level\n");
- printf(" -l logfile\n");
- printf(" -L libdir\n");
- exit(0);
-}
-
-int main(int argc, char *argv[])
-{
- char *p, *u;
- const char *libd = dyn_LIBDIR;
- pstring line, wd;
- int opt;
- extern char *optarg;
- extern int optind;
-
- dbf = x_stdout;
- smbw_setup_shared();
-
- while ((opt = getopt(argc, argv, "W:U:R:d:P:l:hL:")) != EOF) {
- switch (opt) {
- case 'L':
- libd = optarg;
- break;
- case 'W':
- smbw_setshared("WORKGROUP", optarg);
- break;
- case 'l':
- smbw_setshared("LOGFILE", optarg);
- break;
- case 'P':
- smbw_setshared("PREFIX", optarg);
- break;
- case 'd':
- smbw_setshared("DEBUG", optarg);
- break;
- case 'U':
- p = strchr_m(optarg,'%');
- if (p) {
- *p=0;
- smbw_setshared("PASSWORD",p+1);
- }
- smbw_setshared("USER", optarg);
- break;
- case 'R':
- smbw_setshared("RESOLVE_ORDER",optarg);
- break;
-
- case 'h':
- default:
- smbsh_usage();
- }
- }
-
-
- if (!smbw_getshared("USER")) {
- printf("Username: ");
- fflush(stdout);
- u = fgets_slash(line, sizeof(line)-1, x_stdin);
- smbw_setshared("USER", u);
- }
-
- if (!smbw_getshared("PASSWORD")) {
- p = getpass("Password: ");
- smbw_setshared("PASSWORD", p);
- }
-
- setenv("PS1", "smbsh$ ", 1);
-
- sys_getwd(wd);
-
- slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
-
- smbw_setshared(line, wd);
-
- slprintf(line,sizeof(line)-1,"%s/smbwrapper.so", libd);
- setenv("LD_PRELOAD", line, 1);
-
- slprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so", libd);
-
- if (file_exist(line, NULL)) {
- slprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so:DEFAULT", libd);
- setenv("_RLD_LIST", line, 1);
- slprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd);
- setenv("_RLDN32_LIST", line, 1);
- } else {
- slprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd);
- setenv("_RLD_LIST", line, 1);
- }
-
- {
- char *shellpath = getenv("SHELL");
- if(shellpath)
- execl(shellpath,"smbsh",NULL);
- else
- execl("/bin/sh","smbsh",NULL);
- }
- printf("launch failed!\n");
- return 1;
-}
diff --git a/source/smbwrapper/smbsh.in b/source/smbwrapper/smbsh.in
deleted file mode 100644
index 323f0916993..00000000000
--- a/source/smbwrapper/smbsh.in
+++ /dev/null
@@ -1,54 +0,0 @@
-#! /bin/sh
-
-SMBW_LIBDIR=${SMBW_LIBDIR-@builddir@/smbwrapper}
-
-if [ ! -f ${SMBW_LIBDIR}/smbwrapper.so ]; then
- echo You need to set LIBDIR in smbsh
- exit
-fi
-
-# a simple launcher for the smbwrapper.so preloadde library
-
-if [ x"${SMBW_USER+set}" != x"set" ]; then
- echo username?
- read user
- SMBW_USER=$user
- export SMBW_USER
-fi
-
-# this doesn't hide the password - we need a proper launch app for that
-if [ x"${SMBW_PASSWORD+set}" != x"set" ]; then
- echo password?
- read pass
- SMBW_PASSWORD=$pass
- export SMBW_PASSWORD
-fi
-
-PWD=`pwd`
-export PWD
-PS1='smbsh$ '
-export PS1
-
-
-host_os=@HOST_OS@
-
-case "$host_os" in
- *irix*)
- _RLDN32_LIST=$SMBW_LIBDIR/smbwrapper.so:DEFAULT
- _RLD_LIST=$SMBW_LIBDIR/smbwrapper.32.so:DEFAULT
- export _RLDN32_LIST
- export _RLD_LIST
- ;;
- *osf*)
- _RLD_LIST=$SMBW_LIBDIR/smbwrapper.so:DEFAULT
- export _RLD_LIST
- ;;
- *)
- LD_PRELOAD=$SMBW_LIBDIR/smbwrapper.so
- export LD_PRELOAD
- ;;
-esac
-
-echo starting smbwrapper on $host_os
-
-exec ${SMBW_SHELL-${SHELL-/bin/sh}} ${1+"$@"}
diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c
deleted file mode 100644
index d4a5b51af4e..00000000000
--- a/source/smbwrapper/smbw.c
+++ /dev/null
@@ -1,1562 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper functions
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "realcalls.h"
-
-pstring smbw_cwd;
-
-static struct smbw_file *smbw_files;
-static struct smbw_server *smbw_srvs;
-
-struct bitmap *smbw_file_bmap;
-
-fstring smbw_prefix = SMBW_PREFIX;
-
-int smbw_busy=0;
-
-/* needs to be here because of dumb include files on some systems */
-int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
-
-
-/*****************************************************
-initialise structures
-*******************************************************/
-void smbw_init(void)
-{
- extern BOOL in_client;
- static int initialised;
- char *p;
- int eno;
- pstring line;
-
- if (initialised) return;
- initialised = 1;
-
- eno = errno;
-
- smbw_busy++;
-
- DEBUGLEVEL = 0;
- setup_logging("smbsh",True);
-
- dbf = x_stderr;
-
- if ((p=smbw_getshared("LOGFILE"))) {
- dbf = sys_fopen(p, "a");
- }
-
- smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
- if (!smbw_file_bmap) {
- exit(1);
- }
-
- in_client = True;
-
- load_interfaces();
-
- if ((p=smbw_getshared("SERVICESF"))) {
- pstrcpy(dyn_CONFIGFILE, p);
- }
-
- lp_load(dyn_CONFIGFILE,True,False,False,True);
-
- if (!init_names())
- exit(1);
-
- if ((p=smbw_getshared("DEBUG"))) {
- DEBUGLEVEL = atoi(p);
- }
-
- if ((p=smbw_getshared("RESOLVE_ORDER"))) {
- lp_set_name_resolve_order(p);
- }
-
- if ((p=smbw_getshared("PREFIX"))) {
- slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
- all_string_sub(smbw_prefix,"//", "/", 0);
- DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
- }
-
- slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
-
- p = smbw_getshared(line);
- if (!p) {
- sys_getwd(smbw_cwd);
- }
- pstrcpy(smbw_cwd, p);
- DEBUG(4,("Initial cwd is %s\n", smbw_cwd));
-
- smbw_busy--;
-
- set_maxfiles(SMBW_MAX_OPEN);
-
- BlockSignals(True,SIGPIPE);
-
- errno = eno;
-}
-
-/*****************************************************
-determine if a file descriptor is a smb one
-*******************************************************/
-int smbw_fd(int fd)
-{
- if (smbw_busy) return 0;
- return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
-}
-
-/*****************************************************
-determine if a file descriptor is an internal smbw fd
-*******************************************************/
-int smbw_local_fd(int fd)
-{
- struct smbw_server *srv;
-
- smbw_init();
-
- if (smbw_busy) return 0;
- if (smbw_shared_fd(fd)) return 1;
-
- for (srv=smbw_srvs;srv;srv=srv->next) {
- if (srv->cli.fd == fd) return 1;
- }
-
- return 0;
-}
-
-/*****************************************************
-a crude inode number generator
-*******************************************************/
-ino_t smbw_inode(const char *name)
-{
- if (!*name) return 2;
- return (ino_t)str_checksum(name);
-}
-
-/*****************************************************
-remove redundent stuff from a filename
-*******************************************************/
-void clean_fname(char *name)
-{
- char *p, *p2;
- int l;
- int modified = 1;
-
- if (!name) return;
-
- while (modified) {
- modified = 0;
-
- DEBUG(5,("cleaning %s\n", name));
-
- if ((p=strstr(name,"/./"))) {
- modified = 1;
- while (*p) {
- p[0] = p[2];
- p++;
- }
- }
-
- if ((p=strstr(name,"//"))) {
- modified = 1;
- while (*p) {
- p[0] = p[1];
- p++;
- }
- }
-
- if (strcmp(name,"/../")==0) {
- modified = 1;
- name[1] = 0;
- }
-
- if ((p=strstr(name,"/../"))) {
- modified = 1;
- for (p2=(p>name?p-1:p);p2>name;p2--) {
- if (p2[0] == '/') break;
- }
- while (*p2) {
- p2[0] = p2[3];
- p2++;
- }
- }
-
- if (strcmp(name,"/..")==0) {
- modified = 1;
- name[1] = 0;
- }
-
- l = strlen(name);
- p = l>=3?(name+l-3):name;
- if (strcmp(p,"/..")==0) {
- modified = 1;
- for (p2=p-1;p2>name;p2--) {
- if (p2[0] == '/') break;
- }
- if (p2==name) {
- p[0] = '/';
- p[1] = 0;
- } else {
- p2[0] = 0;
- }
- }
-
- l = strlen(name);
- p = l>=2?(name+l-2):name;
- if (strcmp(p,"/.")==0) {
- if (p == name) {
- p[1] = 0;
- } else {
- p[0] = 0;
- }
- }
-
- if (strncmp(p=name,"./",2) == 0) {
- modified = 1;
- do {
- p[0] = p[2];
- } while (*p++);
- }
-
- l = strlen(p=name);
- if (l > 1 && p[l-1] == '/') {
- modified = 1;
- p[l-1] = 0;
- }
- }
-}
-
-
-
-/*****************************************************
-find a workgroup (any workgroup!) that has a master
-browser on the local network
-*******************************************************/
-static char *smbw_find_workgroup(void)
-{
- fstring server;
- char *p;
- struct in_addr *ip_list = NULL;
- int count = 0;
- int i;
-
- /* first off see if an existing workgroup name exists */
- p = smbw_getshared("WORKGROUP");
- if (!p) p = lp_workgroup();
-
- slprintf(server, sizeof(server), "%s#1D", p);
- if (smbw_server(server, "IPC$")) return p;
-
- /* go looking for workgroups */
- if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
- DEBUG(1,("No workgroups found!"));
- return p;
- }
-
- for (i=0;i<count;i++) {
- static fstring name;
- if (name_status_find("*", 0, 0x1d, ip_list[i], name)) {
- slprintf(server, sizeof(server), "%s#1D", name);
- if (smbw_server(server, "IPC$")) {
- smbw_setshared("WORKGROUP", name);
- SAFE_FREE(ip_list);
- return name;
- }
- }
- }
-
- SAFE_FREE(ip_list);
-
- return p;
-}
-
-/*****************************************************
-parse a smb path into its components.
-server is one of
- 1) the name of the SMB server
- 2) WORKGROUP#1D for share listing
- 3) WORKGROUP#__ for workgroup listing
-share is the share on the server to query
-path is the SMB path on the server
-return the full path (ie. add cwd if needed)
-*******************************************************/
-char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
-{
- static pstring s;
- char *p;
- int len;
- fstring workgroup;
-
- /* add cwd if necessary */
- if (fname[0] != '/') {
- slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname);
- } else {
- pstrcpy(s, fname);
- }
- clean_fname(s);
-
- /* see if it has the right prefix */
- len = strlen(smbw_prefix)-1;
- if (strncmp(s,smbw_prefix,len) ||
- (s[len] != '/' && s[len] != 0)) return s;
-
- /* ok, its for us. Now parse out the workgroup, share etc. */
- p = s+len;
- if (*p == '/') p++;
- if (!next_token(&p, workgroup, "/", sizeof(fstring))) {
- /* we're in /smb - give a list of workgroups */
- slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup());
- fstrcpy(share,"IPC$");
- pstrcpy(path,"");
- return s;
- }
-
- if (!next_token(&p, server, "/", sizeof(fstring))) {
- /* we are in /smb/WORKGROUP */
- slprintf(server,sizeof(fstring), "%s#1D", workgroup);
- fstrcpy(share,"IPC$");
- pstrcpy(path,"");
- }
-
- if (!next_token(&p, share, "/", sizeof(fstring))) {
- /* we are in /smb/WORKGROUP/SERVER */
- fstrcpy(share,"IPC$");
- pstrcpy(path,"");
- }
-
- pstrcpy(path, p);
-
- all_string_sub(path, "/", "\\", 0);
-
- return s;
-}
-
-/*****************************************************
-determine if a path name (possibly relative) is in the
-smb name space
-*******************************************************/
-int smbw_path(const char *path)
-{
- fstring server, share;
- pstring s;
- char *cwd;
- int len;
-
- if(!path)
- return 0;
-
- /* this is needed to prevent recursion with the BSD malloc which
- opens /etc/malloc.conf on the first call */
- if (strncmp(path,"/etc/", 5) == 0) {
- return 0;
- }
-
- smbw_init();
-
- len = strlen(smbw_prefix)-1;
-
- if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
- return 0;
- }
-
- if (smbw_busy) return 0;
-
- DEBUG(3,("smbw_path(%s)\n", path));
-
- cwd = smbw_parse_path(path, server, share, s);
-
- if (strncmp(cwd,smbw_prefix,len) == 0 &&
- (cwd[len] == '/' || cwd[len] == 0)) {
- return 1;
- }
-
- return 0;
-}
-
-/*****************************************************
-return a unix errno from a SMB error pair
-*******************************************************/
-int smbw_errno(struct cli_state *c)
-{
- return cli_errno(c);
-}
-
-/* Return a username and password given a server and share name */
-
-void get_envvar_auth_data(char *server, char *share, char **workgroup,
- char **username, char **password)
-{
- /* Fall back to shared memory/environment variables */
-
- *username = smbw_getshared("USER");
- if (!*username) *username = getenv("USER");
- if (!*username) *username = "guest";
-
- *workgroup = smbw_getshared("WORKGROUP");
- if (!*workgroup) *workgroup = lp_workgroup();
-
- *password = smbw_getshared("PASSWORD");
- if (!*password) *password = "";
-}
-
-static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;
-
-/*****************************************************
-set the get auth data function
-******************************************************/
-void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn)
-{
- get_auth_data_fn = fn;
-}
-
-/*****************************************************
-return a connection to a server (existing or new)
-*******************************************************/
-struct smbw_server *smbw_server(char *server, char *share)
-{
- struct smbw_server *srv=NULL;
- struct cli_state c;
- char *username;
- char *password;
- char *workgroup;
- struct nmb_name called, calling;
- char *p, *server_n = server;
- fstring group;
- pstring ipenv;
- struct in_addr ip;
-
- zero_ip(&ip);
- ZERO_STRUCT(c);
-
- get_auth_data_fn(server, share, &workgroup, &username, &password);
-
- /* try to use an existing connection */
- for (srv=smbw_srvs;srv;srv=srv->next) {
- if (strcmp(server,srv->server_name)==0 &&
- strcmp(share,srv->share_name)==0 &&
- strcmp(workgroup,srv->workgroup)==0 &&
- strcmp(username, srv->username) == 0)
- return srv;
- }
-
- if (server[0] == 0) {
- errno = EPERM;
- return NULL;
- }
-
- make_nmb_name(&calling, global_myname(), 0x0);
- make_nmb_name(&called , server, 0x20);
-
- DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
-
- if ((p=strchr_m(server_n,'#')) &&
- (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
- struct in_addr sip;
- pstring s;
-
- fstrcpy(group, server_n);
- p = strchr_m(group,'#');
- *p = 0;
-
- /* cache the workgroup master lookup */
- slprintf(s,sizeof(s)-1,"MASTER_%s", group);
- if (!(server_n = smbw_getshared(s))) {
- if (!find_master_ip(group, &sip)) {
- errno = ENOENT;
- return NULL;
- }
- fstrcpy(group, inet_ntoa(sip));
- server_n = group;
- smbw_setshared(s,server_n);
- }
- }
-
- DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
-
- again:
- slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
-
- zero_ip(&ip);
- if ((p=smbw_getshared(ipenv))) {
- ip = *(interpret_addr2(p));
- }
-
- /* have to open a new connection */
- if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
- errno = ENOENT;
- return NULL;
- }
-
- if (!cli_session_request(&c, &calling, &called)) {
- cli_shutdown(&c);
- if (strcmp(called.name, "*SMBSERVER")) {
- make_nmb_name(&called , "*SMBSERVER", 0x20);
- goto again;
- }
- errno = ENOENT;
- return NULL;
- }
-
- DEBUG(4,(" session request ok\n"));
-
- if (!cli_negprot(&c)) {
- cli_shutdown(&c);
- errno = ENOENT;
- return NULL;
- }
-
- if (!cli_session_setup(&c, username,
- password, strlen(password),
- password, strlen(password),
- workgroup) &&
- /* try an anonymous login if it failed */
- !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
- cli_shutdown(&c);
- errno = EPERM;
- return NULL;
- }
-
- DEBUG(4,(" session setup ok\n"));
-
- if (!cli_send_tconX(&c, share, "?????",
- password, strlen(password)+1)) {
- errno = smbw_errno(&c);
- cli_shutdown(&c);
- return NULL;
- }
-
- smbw_setshared(ipenv,inet_ntoa(ip));
-
- DEBUG(4,(" tconx ok\n"));
-
- srv = SMB_MALLOC_P(struct smbw_server);
- if (!srv) {
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(srv);
-
- srv->cli = c;
-
- srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
-
- srv->server_name = SMB_STRDUP(server);
- if (!srv->server_name) {
- errno = ENOMEM;
- goto failed;
- }
-
- srv->share_name = SMB_STRDUP(share);
- if (!srv->share_name) {
- errno = ENOMEM;
- goto failed;
- }
-
- srv->workgroup = SMB_STRDUP(workgroup);
- if (!srv->workgroup) {
- errno = ENOMEM;
- goto failed;
- }
-
- srv->username = SMB_STRDUP(username);
- if (!srv->username) {
- errno = ENOMEM;
- goto failed;
- }
-
- /* some programs play with file descriptors fairly intimately. We
- try to get out of the way by duping to a high fd number */
- if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
- if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
- srv->cli.fd+SMBW_CLI_FD) {
- close(srv->cli.fd);
- srv->cli.fd += SMBW_CLI_FD;
- }
- }
-
- DLIST_ADD(smbw_srvs, srv);
-
- return srv;
-
- failed:
- cli_shutdown(&c);
- if (!srv) return NULL;
-
- SAFE_FREE(srv->server_name);
- SAFE_FREE(srv->share_name);
- SAFE_FREE(srv);
- return NULL;
-}
-
-
-/*****************************************************
-map a fd to a smbw_file structure
-*******************************************************/
-struct smbw_file *smbw_file(int fd)
-{
- struct smbw_file *file;
-
- for (file=smbw_files;file;file=file->next) {
- if (file->fd == fd) return file;
- }
- return NULL;
-}
-
-/*****************************************************
-a wrapper for open()
-*******************************************************/
-int smbw_open(const char *fname, int flags, mode_t mode)
-{
- fstring server, share;
- pstring path;
- struct smbw_server *srv=NULL;
- int eno=0, fd = -1;
- struct smbw_file *file=NULL;
-
- smbw_init();
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (path[strlen(path)-1] == '\\') {
- fd = -1;
- } else {
- fd = cli_open(&srv->cli, path, flags, DENY_NONE);
- }
- if (fd == -1) {
- /* it might be a directory. Maybe we should use chkpath? */
- eno = smbw_errno(&srv->cli);
- fd = smbw_dir_open(fname);
- if (fd == -1) errno = eno;
- smbw_busy--;
- return fd;
- }
-
- file = SMB_MALLOC_P(struct smbw_file);
- if (!file) {
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(file);
-
- file->f = SMB_MALLOC_P(struct smbw_filedes);
- if (!file->f) {
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(file->f);
-
- file->f->cli_fd = fd;
- file->f->fname = SMB_STRDUP(path);
- if (!file->f->fname) {
- errno = ENOMEM;
- goto failed;
- }
- file->srv = srv;
- file->fd = open(SMBW_DUMMY, O_WRONLY);
- if (file->fd == -1) {
- errno = EMFILE;
- goto failed;
- }
-
- if (bitmap_query(smbw_file_bmap, file->fd)) {
- DEBUG(0,("ERROR: fd used in smbw_open\n"));
- errno = EIO;
- goto failed;
- }
-
- file->f->ref_count=1;
-
- bitmap_set(smbw_file_bmap, file->fd);
-
- DLIST_ADD(smbw_files, file);
-
- DEBUG(4,("opened %s\n", fname));
-
- smbw_busy--;
- return file->fd;
-
- failed:
- if (fd != -1) {
- cli_close(&srv->cli, fd);
- }
- if (file) {
- if (file->f) {
- SAFE_FREE(file->f->fname);
- SAFE_FREE(file->f);
- }
- SAFE_FREE(file);
- }
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for pread()
-*******************************************************/
-ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
-{
- struct smbw_file *file;
- int ret;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- smbw_busy--;
- return -1;
- }
-
- ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
-
- if (ret == -1) {
- errno = smbw_errno(&file->srv->cli);
- smbw_busy--;
- return -1;
- }
-
- smbw_busy--;
- return ret;
-}
-
-/*****************************************************
-a wrapper for read()
-*******************************************************/
-ssize_t smbw_read(int fd, void *buf, size_t count)
-{
- struct smbw_file *file;
- int ret;
-
- DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- smbw_busy--;
- return -1;
- }
-
- ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
- file->f->offset, count);
-
- if (ret == -1) {
- errno = smbw_errno(&file->srv->cli);
- smbw_busy--;
- return -1;
- }
-
- file->f->offset += ret;
-
- DEBUG(4,(" -> %d\n", ret));
-
- smbw_busy--;
- return ret;
-}
-
-
-
-/*****************************************************
-a wrapper for write()
-*******************************************************/
-ssize_t smbw_write(int fd, void *buf, size_t count)
-{
- struct smbw_file *file;
- int ret;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- smbw_busy--;
- return -1;
- }
-
- ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
-
- if (ret == -1) {
- errno = smbw_errno(&file->srv->cli);
- smbw_busy--;
- return -1;
- }
-
- file->f->offset += ret;
-
- smbw_busy--;
- return ret;
-}
-
-/*****************************************************
-a wrapper for pwrite()
-*******************************************************/
-ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
-{
- struct smbw_file *file;
- int ret;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- smbw_busy--;
- return -1;
- }
-
- ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
-
- if (ret == -1) {
- errno = smbw_errno(&file->srv->cli);
- smbw_busy--;
- return -1;
- }
-
- smbw_busy--;
- return ret;
-}
-
-/*****************************************************
-a wrapper for close()
-*******************************************************/
-int smbw_close(int fd)
-{
- struct smbw_file *file;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- int ret = smbw_dir_close(fd);
- smbw_busy--;
- return ret;
- }
-
- if (file->f->ref_count == 1 &&
- !cli_close(&file->srv->cli, file->f->cli_fd)) {
- errno = smbw_errno(&file->srv->cli);
- smbw_busy--;
- return -1;
- }
-
-
- bitmap_clear(smbw_file_bmap, file->fd);
- close(file->fd);
-
- DLIST_REMOVE(smbw_files, file);
-
- file->f->ref_count--;
- if (file->f->ref_count == 0) {
- SAFE_FREE(file->f->fname);
- SAFE_FREE(file->f);
- }
- ZERO_STRUCTP(file);
- SAFE_FREE(file);
-
- smbw_busy--;
-
- return 0;
-}
-
-
-/*****************************************************
-a wrapper for fcntl()
-*******************************************************/
-int smbw_fcntl(int fd, int cmd, long arg)
-{
- return 0;
-}
-
-
-/*****************************************************
-a wrapper for access()
-*******************************************************/
-int smbw_access(const char *name, int mode)
-{
- struct stat st;
-
- DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
-
- if (smbw_stat(name, &st)) return -1;
-
- if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
- ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
- ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
- errno = EACCES;
- return -1;
- }
-
- return 0;
-}
-
-/*****************************************************
-a wrapper for realink() - needed for correct errno setting
-*******************************************************/
-int smbw_readlink(const char *path, char *buf, size_t bufsize)
-{
- struct stat st;
- int ret;
-
- ret = smbw_stat(path, &st);
- if (ret != 0) {
- DEBUG(4,("readlink(%s) failed\n", path));
- return -1;
- }
-
- /* it exists - say it isn't a link */
- DEBUG(4,("readlink(%s) not a link\n", path));
-
- errno = EINVAL;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for unlink()
-*******************************************************/
-int smbw_unlink(const char *fname)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
- int job = smbw_stat_printjob(srv, path, NULL, NULL);
- if (job == -1) {
- goto failed;
- }
- if (cli_printjob_del(&srv->cli, job) != 0) {
- goto failed;
- }
- } else if (!cli_unlink(&srv->cli, path)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for rename()
-*******************************************************/
-int smbw_rename(const char *oldname, const char *newname)
-{
- struct smbw_server *srv;
- fstring server1, share1;
- pstring path1;
- fstring server2, share2;
- pstring path2;
-
- if (!oldname || !newname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(oldname, server1, share1, path1);
- smbw_parse_path(newname, server2, share2, path2);
-
- if (strcmp(server1, server2) || strcmp(share1, share2)) {
- /* can't cross filesystems */
- errno = EXDEV;
- return -1;
- }
-
- /* get a connection to the server */
- srv = smbw_server(server1, share1);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (!cli_rename(&srv->cli, path1, path2)) {
- int eno = smbw_errno(&srv->cli);
- if (eno != EEXIST ||
- !cli_unlink(&srv->cli, path2) ||
- !cli_rename(&srv->cli, path1, path2)) {
- errno = eno;
- goto failed;
- }
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for utime and utimes
-*******************************************************/
-static int smbw_settime(const char *fname, time_t t)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
- uint16 mode;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- if (!cli_setatr(&srv->cli, path, mode, t)) {
- /* some servers always refuse directory changes */
- if (!(mode & aDIR)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-/*****************************************************
-a wrapper for utime
-*******************************************************/
-int smbw_utime(const char *fname, void *buf)
-{
- struct utimbuf *tbuf = (struct utimbuf *)buf;
- return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
-}
-
-/*****************************************************
-a wrapper for utime
-*******************************************************/
-int smbw_utimes(const char *fname, void *buf)
-{
- struct timeval *tbuf = (struct timeval *)buf;
- return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
-}
-
-
-/*****************************************************
-a wrapper for chown()
-*******************************************************/
-int smbw_chown(const char *fname, uid_t owner, gid_t group)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
- uint16 mode;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- /* assume success */
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-/*****************************************************
-a wrapper for chmod()
-*******************************************************/
-int smbw_chmod(const char *fname, mode_t newmode)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
- uint32 mode;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- mode = 0;
-
- if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
- if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
- if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
- if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
-
- if (!cli_setatr(&srv->cli, path, mode, 0)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-/*****************************************************
-a wrapper for lseek()
-*******************************************************/
-off_t smbw_lseek(int fd, off_t offset, int whence)
-{
- struct smbw_file *file;
- SMB_OFF_T size;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- off_t ret = smbw_dir_lseek(fd, offset, whence);
- smbw_busy--;
- return ret;
- }
-
- switch (whence) {
- case SEEK_SET:
- file->f->offset = offset;
- break;
- case SEEK_CUR:
- file->f->offset += offset;
- break;
- case SEEK_END:
- if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
- NULL, &size, NULL, NULL, NULL,
- NULL, NULL) &&
- !cli_getattrE(&file->srv->cli, file->f->cli_fd,
- NULL, &size, NULL, NULL, NULL)) {
- errno = EINVAL;
- smbw_busy--;
- return -1;
- }
- file->f->offset = size + offset;
- break;
- }
-
- smbw_busy--;
- return file->f->offset;
-}
-
-
-/*****************************************************
-a wrapper for dup()
-*******************************************************/
-int smbw_dup(int fd)
-{
- int fd2;
- struct smbw_file *file, *file2;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- goto failed;
- }
-
- fd2 = dup(file->fd);
- if (fd2 == -1) {
- goto failed;
- }
-
- if (bitmap_query(smbw_file_bmap, fd2)) {
- DEBUG(0,("ERROR: fd already open in dup!\n"));
- errno = EIO;
- goto failed;
- }
-
- file2 = SMB_MALLOC_P(struct smbw_file);
- if (!file2) {
- close(fd2);
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(file2);
-
- *file2 = *file;
- file2->fd = fd2;
-
- file->f->ref_count++;
-
- bitmap_set(smbw_file_bmap, fd2);
-
- DLIST_ADD(smbw_files, file2);
-
- smbw_busy--;
- return fd2;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for dup2()
-*******************************************************/
-int smbw_dup2(int fd, int fd2)
-{
- struct smbw_file *file, *file2;
-
- smbw_busy++;
-
- file = smbw_file(fd);
- if (!file) {
- errno = EBADF;
- goto failed;
- }
-
- if (bitmap_query(smbw_file_bmap, fd2)) {
- DEBUG(0,("ERROR: fd already open in dup2!\n"));
- errno = EIO;
- goto failed;
- }
-
- if (dup2(file->fd, fd2) != fd2) {
- goto failed;
- }
-
- file2 = SMB_MALLOC_P(struct smbw_file);
- if (!file2) {
- close(fd2);
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(file2);
-
- *file2 = *file;
- file2->fd = fd2;
-
- file->f->ref_count++;
-
- bitmap_set(smbw_file_bmap, fd2);
-
- DLIST_ADD(smbw_files, file2);
-
- smbw_busy--;
- return fd2;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-close a connection to a server
-*******************************************************/
-static void smbw_srv_close(struct smbw_server *srv)
-{
- smbw_busy++;
-
- cli_shutdown(&srv->cli);
-
- SAFE_FREE(srv->server_name);
- SAFE_FREE(srv->share_name);
-
- DLIST_REMOVE(smbw_srvs, srv);
-
- ZERO_STRUCTP(srv);
-
- SAFE_FREE(srv);
-
- smbw_busy--;
-}
-
-/*****************************************************
-when we fork we have to close all connections and files
-in the child
-*******************************************************/
-int smbw_fork(void)
-{
- pid_t child;
- int p[2];
- char c=0;
- pstring line;
-
- struct smbw_file *file, *next_file;
- struct smbw_server *srv, *next_srv;
-
- if (pipe(p)) return real_fork();
-
- child = real_fork();
-
- if (child) {
- /* block the parent for a moment until the sockets are
- closed */
- close(p[1]);
- read(p[0], &c, 1);
- close(p[0]);
- return child;
- }
-
- close(p[0]);
-
- /* close all files */
- for (file=smbw_files;file;file=next_file) {
- next_file = file->next;
- close(file->fd);
- }
-
- /* close all server connections */
- for (srv=smbw_srvs;srv;srv=next_srv) {
- next_srv = srv->next;
- smbw_srv_close(srv);
- }
-
- slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());
- smbw_setshared(line,smbw_cwd);
-
- /* unblock the parent */
- write(p[1], &c, 1);
- close(p[1]);
-
- /* and continue in the child */
- return 0;
-}
-
-#ifndef NO_ACL_WRAPPER
-/*****************************************************
-say no to acls
-*******************************************************/
- int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
-{
- if (cmd == GETACL || cmd == GETACLCNT) return 0;
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef NO_FACL_WRAPPER
-/*****************************************************
-say no to acls
-*******************************************************/
- int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
-{
- if (cmd == GETACL || cmd == GETACLCNT) return 0;
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
-#ifdef HAVE_STAT64
-/* this can't be in wrapped.c because of include conflicts */
- void stat64_convert(struct stat *st, struct stat64 *st64)
-{
- st64->st_size = st->st_size;
- st64->st_mode = st->st_mode;
- st64->st_ino = st->st_ino;
- st64->st_dev = st->st_dev;
- st64->st_rdev = st->st_rdev;
- st64->st_nlink = st->st_nlink;
- st64->st_uid = st->st_uid;
- st64->st_gid = st->st_gid;
- st64->st_atime = st->st_atime;
- st64->st_mtime = st->st_mtime;
- st64->st_ctime = st->st_ctime;
-#ifdef HAVE_STAT_ST_BLKSIZE
- st64->st_blksize = st->st_blksize;
-#endif
-#ifdef HAVE_STAT_ST_BLOCKS
- st64->st_blocks = st->st_blocks;
-#endif
-}
-#endif
-
-#ifdef HAVE_READDIR64
- void dirent64_convert(struct dirent *d, struct dirent64 *d64)
-{
- d64->d_ino = d->d_ino;
- d64->d_off = d->d_off;
- d64->d_reclen = d->d_reclen;
- pstrcpy(d64->d_name, d->d_name);
-}
-#endif
-#endif
-
-
-#ifdef HAVE___XSTAT
-/* Definition of `struct stat' used in the linux kernel.. */
-struct kernel_stat {
- unsigned short int st_dev;
- unsigned short int __pad1;
- unsigned long int st_ino;
- unsigned short int st_mode;
- unsigned short int st_nlink;
- unsigned short int st_uid;
- unsigned short int st_gid;
- unsigned short int st_rdev;
- unsigned short int __pad2;
- unsigned long int st_size;
- unsigned long int st_blksize;
- unsigned long int st_blocks;
- unsigned long int st_atime_;
- unsigned long int __unused1;
- unsigned long int st_mtime_;
- unsigned long int __unused2;
- unsigned long int st_ctime_;
- unsigned long int __unused3;
- unsigned long int __unused4;
- unsigned long int __unused5;
-};
-
-/*
- * Prototype for gcc in 'fussy' mode.
- */
- void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
- void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
-{
-#ifdef _STAT_VER_LINUX_OLD
- if (vers == _STAT_VER_LINUX_OLD) {
- memcpy(st, kbuf, sizeof(*st));
- return;
- }
-#endif
-
- ZERO_STRUCTP(st);
-
- st->st_dev = kbuf->st_dev;
- st->st_ino = kbuf->st_ino;
- st->st_mode = kbuf->st_mode;
- st->st_nlink = kbuf->st_nlink;
- st->st_uid = kbuf->st_uid;
- st->st_gid = kbuf->st_gid;
- st->st_rdev = kbuf->st_rdev;
- st->st_size = kbuf->st_size;
-#ifdef HAVE_STAT_ST_BLKSIZE
- st->st_blksize = kbuf->st_blksize;
-#endif
-#ifdef HAVE_STAT_ST_BLOCKS
- st->st_blocks = kbuf->st_blocks;
-#endif
- st->st_atime = kbuf->st_atime_;
- st->st_mtime = kbuf->st_mtime_;
- st->st_ctime = kbuf->st_ctime_;
-}
-#endif
diff --git a/source/smbwrapper/smbw.h b/source/smbwrapper/smbw.h
deleted file mode 100644
index 3f0b1cbb443..00000000000
--- a/source/smbwrapper/smbw.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper functions - definitions
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _SMBW_H
-#define _SMBW_H
-
-#define SMBW_PREFIX "/smb/"
-#define SMBW_DUMMY "/dev/null"
-
-#define SMBW_CLI_FD 512
-#define SMBW_MAX_OPEN 8192
-
-#define SMBW_FILE_MODE (S_IFREG | 0444)
-#define SMBW_DIR_MODE (S_IFDIR | 0555)
-
-struct smbw_server {
- struct smbw_server *next, *prev;
- struct cli_state cli;
- char *server_name;
- char *share_name;
- char *workgroup;
- char *username;
- dev_t dev;
- BOOL no_pathinfo2;
-};
-
-struct smbw_filedes {
- int cli_fd;
- int ref_count;
- char *fname;
- off_t offset;
-};
-
-struct smbw_file {
- struct smbw_file *next, *prev;
- struct smbw_filedes *f;
- int fd;
- struct smbw_server *srv;
-};
-
-struct smbw_dir {
- struct smbw_dir *next, *prev;
- int fd;
- int offset, count, malloced;
- struct smbw_server *srv;
- struct file_info *list;
- char *path;
-};
-
-typedef void (*smbw_get_auth_data_fn)(char *server, char *share,
- char **workgroup, char **username,
- char **password);
-
-#endif /* _SMBW_H */
diff --git a/source/smbwrapper/smbw_cache.c b/source/smbwrapper/smbw_cache.c
deleted file mode 100644
index cfa8ab1f76c..00000000000
--- a/source/smbwrapper/smbw_cache.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper directory functions
- Copyright (C) Tim Potter 2000
-
- 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"
-
-/* We cache lists of workgroups, lists of servers in workgroups, and lists
- of shares exported by servers. */
-
-#define CACHE_TIMEOUT 30
-
-struct name_list {
- struct name_list *prev, *next;
- char *name;
- uint32 stype;
- char *comment;
-};
-
-struct cached_names {
- struct cached_names *prev, *next;
- char *key;
- struct name_list *name_list;
- time_t cache_timeout;
- int result;
-};
-
-static struct cached_names *cached_names = NULL;
-
-/* Find a list of cached name for a workgroup, server or share list */
-
-static struct cached_names *find_cached_names(char *key)
-{
- struct cached_names *tmp;
-
- for (tmp = cached_names; tmp; tmp = tmp->next) {
- if (strequal(tmp->key, key)) {
- return tmp;
- }
- }
-
- return NULL;
-}
-
-/* Add a name to a list stored in the state variable */
-
-static void add_cached_names(const char *name, uint32 stype,
- const char *comment, void *state)
-{
- struct name_list **name_list = (struct name_list **)state;
- struct name_list *new_name;
-
- new_name = SMB_MALLOC_P(struct name_list);
- if (!new_name) return;
-
- ZERO_STRUCTP(new_name);
-
- new_name->name = SMB_STRDUP(name);
- new_name->stype = stype;
- new_name->comment = SMB_STRDUP(comment);
-
- DLIST_ADD(*name_list, new_name);
-}
-
-static void free_name_list(struct name_list *name_list)
-{
- struct name_list *tmp = name_list;
-
- while(tmp) {
- struct name_list *next;
-
- next = tmp->next;
-
- SAFE_FREE(tmp->name);
- SAFE_FREE(tmp->comment);
- SAFE_FREE(tmp);
-
- tmp = next;
- }
-}
-
-/* Wrapper for NetServerEnum function */
-
-BOOL smbw_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
- void (*fn)(const char *, uint32, const char *, void *),
- void *state)
-{
- struct cached_names *names;
- struct name_list *tmp;
- time_t now = time(NULL);
- char key[PATH_MAX];
- BOOL result = True;
-
- slprintf(key, PATH_MAX - 1, "%s/%s#%s", cli->desthost,
- workgroup, (stype == SV_TYPE_DOMAIN_ENUM ? "DOM" : "SRV"));
-
- names = find_cached_names(key);
-
- if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) {
- struct cached_names *new_names = NULL;
-
- /* No names cached for this workgroup */
-
- if (names == NULL) {
- new_names = SMB_MALLOC_P(struct cached_names);
-
- ZERO_STRUCTP(new_names);
- DLIST_ADD(cached_names, new_names);
-
- } else {
-
- /* Dispose of out of date name list */
-
- free_name_list(names->name_list);
- names->name_list = NULL;
-
- new_names = names;
- }
-
- result = cli_NetServerEnum(cli, workgroup, stype,
- add_cached_names,
- &new_names->name_list);
-
- new_names->cache_timeout = now;
- new_names->result = result;
- new_names->key = SMB_STRDUP(key);
-
- names = new_names;
- }
-
- /* Return names by running callback function. */
-
- for (tmp = names->name_list; tmp; tmp = tmp->next)
- fn(tmp->name, stype, tmp->comment, state);
-
- return names->result;
-}
-
-/* Wrapper for RNetShareEnum function */
-
-int smbw_RNetShareEnum(struct cli_state *cli,
- void (*fn)(const char *, uint32, const char *, void *),
- void *state)
-{
- struct cached_names *names;
- struct name_list *tmp;
- time_t now = time(NULL);
- char key[PATH_MAX];
-
- slprintf(key, PATH_MAX - 1, "SHARE/%s", cli->desthost);
-
- names = find_cached_names(key);
-
- if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) {
- struct cached_names *new_names = NULL;
-
- /* No names cached for this server */
-
- if (names == NULL) {
- new_names = SMB_MALLOC_P(struct cached_names);
-
- ZERO_STRUCTP(new_names);
- DLIST_ADD(cached_names, new_names);
-
- } else {
-
- /* Dispose of out of date name list */
-
- free_name_list(names->name_list);
- names->name_list = NULL;
-
- new_names = names;
- }
-
- new_names->result = cli_RNetShareEnum(cli, add_cached_names,
- &new_names->name_list);
-
- new_names->cache_timeout = now;
- new_names->key = SMB_STRDUP(key);
-
- names = new_names;
- }
-
- /* Return names by running callback function. */
-
- for (tmp = names->name_list; tmp; tmp = tmp->next)
- fn(tmp->name, tmp->stype, tmp->comment, state);
-
- return names->result;
-}
diff --git a/source/smbwrapper/smbw_dir.c b/source/smbwrapper/smbw_dir.c
deleted file mode 100644
index a5bf10b29e0..00000000000
--- a/source/smbwrapper/smbw_dir.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper directory functions
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "realcalls.h"
-
-extern pstring smbw_cwd;
-extern fstring smbw_prefix;
-
-static struct smbw_dir *smbw_dirs;
-
-extern struct bitmap *smbw_file_bmap;
-
-extern int smbw_busy;
-
-/*****************************************************
-map a fd to a smbw_dir structure
-*******************************************************/
-struct smbw_dir *smbw_dir(int fd)
-{
- struct smbw_dir *dir;
-
- for (dir=smbw_dirs;dir;dir=dir->next) {
- if (dir->fd == fd) return dir;
- }
- return NULL;
-}
-
-/*****************************************************
-check if a DIR* is one of ours
-*******************************************************/
-int smbw_dirp(DIR *dirp)
-{
- struct smbw_dir *d = (struct smbw_dir *)dirp;
- struct smbw_dir *dir;
-
- for (dir=smbw_dirs;dir;dir=dir->next) {
- if (dir == d) return 1;
- }
- return 0;
-}
-
-/*****************************************************
-free a smbw_dir structure and all entries
-*******************************************************/
-static void free_dir(struct smbw_dir *dir)
-{
- if(!dir) return;
-
- SAFE_FREE(dir->list);
- SAFE_FREE(dir->path);
- ZERO_STRUCTP(dir);
- SAFE_FREE(dir);
-}
-
-static struct smbw_dir *cur_dir;
-
-/*****************************************************
-add a entry to a directory listing
-*******************************************************/
-static void smbw_dir_add(const char *mntpnt, struct file_info *finfo, const char *mask,
- void *state)
-{
- struct file_info *cdl;
-
- DEBUG(5,("%s\n", finfo->name));
-
- if (cur_dir->malloced == cur_dir->count) {
- cdl = (struct file_info *)Realloc(cur_dir->list,
- sizeof(cur_dir->list[0])*
- (cur_dir->count+100), True);
- if (!cdl) {
- /* oops */
- return;
- }
- cur_dir->list = cdl;
- cur_dir->malloced += 100;
- }
-
- cur_dir->list[cur_dir->count] = *finfo;
- cur_dir->count++;
-}
-
-/*****************************************************
-add a entry to a directory listing
-*******************************************************/
-static void smbw_share_add(const char *share, uint32 type,
- const char *comment, void *state)
-{
- struct file_info finfo;
-
- if (strcmp(share,"IPC$") == 0) return;
-
- ZERO_STRUCT(finfo);
-
- pstrcpy(finfo.name, share);
- finfo.mode = aRONLY | aDIR;
-
- smbw_dir_add("\\", &finfo, NULL, NULL);
-}
-
-
-/*****************************************************
-add a server to a directory listing
-*******************************************************/
-static void smbw_server_add(const char *name, uint32 type,
- const char *comment, void *state)
-{
- struct file_info finfo;
-
- ZERO_STRUCT(finfo);
-
- pstrcpy(finfo.name, name);
- finfo.mode = aRONLY | aDIR;
-
- smbw_dir_add("\\", &finfo, NULL, NULL);
-}
-
-
-/*****************************************************
-add a entry to a directory listing
-*******************************************************/
-static void smbw_printjob_add(struct print_job_info *job)
-{
- struct file_info finfo;
-
- ZERO_STRUCT(finfo);
-
- pstrcpy(finfo.name, job->name);
- finfo.mode = aRONLY | aDIR;
- finfo.mtime = job->t;
- finfo.atime = job->t;
- finfo.ctime = job->t;
- finfo.uid = nametouid(job->user);
- finfo.mode = aRONLY;
- finfo.size = job->size;
-
- smbw_dir_add("\\", &finfo, NULL, NULL);
-}
-
-
-/*****************************************************
-open a directory on the server
-*******************************************************/
-int smbw_dir_open(const char *fname)
-{
- fstring server, share;
- pstring path;
- struct smbw_server *srv=NULL;
- struct smbw_dir *dir=NULL;
- pstring mask;
- int fd;
- char *s, *p;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- /* work out what server they are after */
- s = smbw_parse_path(fname, server, share, path);
-
- DEBUG(4,("dir_open share=%s\n", share));
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- dir = SMB_MALLOC_P(struct smbw_dir);
- if (!dir) {
- errno = ENOMEM;
- goto failed;
- }
-
- ZERO_STRUCTP(dir);
-
- cur_dir = dir;
-
- slprintf(mask, sizeof(mask)-1, "%s\\*", path);
- all_string_sub(mask,"\\\\","\\",0);
-
- if ((p=strstr(srv->server_name,"#01"))) {
- *p = 0;
- smbw_server_add(".",0,"", NULL);
- smbw_server_add("..",0,"", NULL);
- smbw_NetServerEnum(&srv->cli, srv->server_name,
- SV_TYPE_DOMAIN_ENUM, smbw_server_add, NULL);
- *p = '#';
- } else if ((p=strstr(srv->server_name,"#1D"))) {
- DEBUG(4,("doing NetServerEnum\n"));
- *p = 0;
- smbw_server_add(".",0,"", NULL);
- smbw_server_add("..",0,"", NULL);
- smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL,
- smbw_server_add, NULL);
- *p = '#';
- } else if ((strcmp(srv->cli.dev,"IPC") == 0) || (strequal(share,"IPC$"))) {
- DEBUG(4,("doing NetShareEnum\n"));
- smbw_share_add(".",0,"", NULL);
- smbw_share_add("..",0,"", NULL);
- if (smbw_RNetShareEnum(&srv->cli, smbw_share_add, NULL) < 0) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
- } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
- smbw_share_add(".",0,"", NULL);
- smbw_share_add("..",0,"", NULL);
- if (cli_print_queue(&srv->cli, smbw_printjob_add) < 0) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
- } else {
-#if 0
- if (strcmp(path,"\\") == 0) {
- smbw_share_add(".",0,"");
- smbw_share_add("..",0,"");
- }
-#endif
- if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR,
- smbw_dir_add, NULL) < 0) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
- }
-
- cur_dir = NULL;
-
- fd = open(SMBW_DUMMY, O_WRONLY);
- if (fd == -1) {
- errno = EMFILE;
- goto failed;
- }
-
- if (bitmap_query(smbw_file_bmap, fd)) {
- DEBUG(0,("ERROR: fd used in smbw_dir_open\n"));
- errno = EIO;
- goto failed;
- }
-
- DLIST_ADD(smbw_dirs, dir);
-
- bitmap_set(smbw_file_bmap, fd);
-
- dir->fd = fd;
- dir->srv = srv;
- dir->path = SMB_STRDUP(s);
-
- DEBUG(4,(" -> %d\n", dir->count));
-
- return dir->fd;
-
- failed:
- free_dir(dir);
-
- return -1;
-}
-
-/*****************************************************
-a wrapper for fstat() on a directory
-*******************************************************/
-int smbw_dir_fstat(int fd, struct stat *st)
-{
- struct smbw_dir *dir;
-
- dir = smbw_dir(fd);
- if (!dir) {
- errno = EBADF;
- return -1;
- }
-
- ZERO_STRUCTP(st);
-
- smbw_setup_stat(st, "", dir->count*DIRP_SIZE, aDIR);
-
- st->st_dev = dir->srv->dev;
-
- return 0;
-}
-
-/*****************************************************
-close a directory handle
-*******************************************************/
-int smbw_dir_close(int fd)
-{
- struct smbw_dir *dir;
-
- dir = smbw_dir(fd);
- if (!dir) {
- errno = EBADF;
- return -1;
- }
-
- bitmap_clear(smbw_file_bmap, dir->fd);
- close(dir->fd);
-
- DLIST_REMOVE(smbw_dirs, dir);
-
- free_dir(dir);
-
- return 0;
-}
-
-/*****************************************************
-a wrapper for getdents()
-*******************************************************/
-int smbw_getdents(unsigned int fd, struct dirent *dirp, int count)
-{
- struct smbw_dir *dir;
- int n=0;
-
- smbw_busy++;
-
- dir = smbw_dir(fd);
- if (!dir) {
- errno = EBADF;
- smbw_busy--;
- return -1;
- }
-
- while (count>=DIRP_SIZE && (dir->offset < dir->count)) {
-#if HAVE_DIRENT_D_OFF
- dirp->d_off = (dir->offset+1)*DIRP_SIZE;
-#endif
- dirp->d_reclen = DIRP_SIZE;
- fstrcpy(&dirp->d_name[0], dir->list[dir->offset].name);
- dirp->d_ino = smbw_inode(dir->list[dir->offset].name);
- dir->offset++;
- count -= dirp->d_reclen;
-#if HAVE_DIRENT_D_OFF
- if (dir->offset == dir->count) {
- dirp->d_off = -1;
- }
-#endif
- dirp = (struct dirent *)(((char *)dirp) + DIRP_SIZE);
- n++;
- }
-
- smbw_busy--;
- return n*DIRP_SIZE;
-}
-
-
-/*****************************************************
-a wrapper for chdir()
-*******************************************************/
-int smbw_chdir(const char *name)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
- uint16 mode = aDIR;
- char *cwd;
- int len;
-
- smbw_init();
-
- len = strlen(smbw_prefix);
-
- if (smbw_busy) return real_chdir(name);
-
- smbw_busy++;
-
- if (!name) {
- errno = EINVAL;
- goto failed;
- }
-
- DEBUG(4,("smbw_chdir(%s)\n", name));
-
- /* work out what server they are after */
- cwd = smbw_parse_path(name, server, share, path);
-
- /* a special case - accept cd to /smb */
- if (strncmp(cwd, smbw_prefix, len-1) == 0 &&
- cwd[len-1] == 0) {
- goto success1;
- }
-
- if (strncmp(cwd,smbw_prefix,strlen(smbw_prefix))) {
- if (real_chdir(cwd) == 0) {
- goto success2;
- }
- goto failed;
- }
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (strncmp(srv->cli.dev,"IPC",3) &&
- !strequal(share, "IPC$") &&
- strncmp(srv->cli.dev,"LPT",3) &&
- !smbw_getatr(srv, path,
- &mode, NULL, NULL, NULL, NULL, NULL)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- if (!(mode & aDIR)) {
- errno = ENOTDIR;
- goto failed;
- }
-
- success1:
- /* we don't want the old directory to be busy */
- real_chdir("/");
-
- success2:
-
- DEBUG(4,("set SMBW_CWD to %s\n", cwd));
-
- pstrcpy(smbw_cwd, cwd);
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for lseek() on directories
-*******************************************************/
-off_t smbw_dir_lseek(int fd, off_t offset, int whence)
-{
- struct smbw_dir *dir;
- off_t ret;
-
- dir = smbw_dir(fd);
- if (!dir) {
- errno = EBADF;
- return -1;
- }
-
- switch (whence) {
- case SEEK_SET:
- dir->offset = offset/DIRP_SIZE;
- break;
- case SEEK_CUR:
- dir->offset += offset/DIRP_SIZE;
- break;
- case SEEK_END:
- dir->offset = (dir->count * DIRP_SIZE) + offset;
- dir->offset /= DIRP_SIZE;
- break;
- }
-
- ret = dir->offset * DIRP_SIZE;
-
- DEBUG(4,(" -> %d\n", (int)ret));
-
- return ret;
-}
-
-
-/*****************************************************
-a wrapper for mkdir()
-*******************************************************/
-int smbw_mkdir(const char *fname, mode_t mode)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (!cli_mkdir(&srv->cli, path)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-/*****************************************************
-a wrapper for rmdir()
-*******************************************************/
-int smbw_rmdir(const char *fname)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
- /* smbw_server sets errno */
- goto failed;
- }
-
- if (!cli_rmdir(&srv->cli, path)) {
- errno = smbw_errno(&srv->cli);
- goto failed;
- }
-
- smbw_busy--;
- return 0;
-
- failed:
- smbw_busy--;
- return -1;
-}
-
-
-/*****************************************************
-a wrapper for getcwd()
-*******************************************************/
-char *smbw_getcwd(char *buf, size_t size)
-{
- smbw_init();
-
- if (smbw_busy) {
- return (char *)real_getcwd(buf, size);
- }
-
- smbw_busy++;
-
- if (!buf) {
- if (size <= 0) size = strlen(smbw_cwd)+1;
- buf = SMB_MALLOC_ARRAY(char, size);
- if (!buf) {
- errno = ENOMEM;
- smbw_busy--;
- return NULL;
- }
- }
-
- if (strlen(smbw_cwd) > size-1) {
- errno = ERANGE;
- smbw_busy--;
- return NULL;
- }
-
- safe_strcpy(buf, smbw_cwd, size);
-
- smbw_busy--;
- return buf;
-}
-
-/*****************************************************
-a wrapper for fchdir()
-*******************************************************/
-int smbw_fchdir(unsigned int fd)
-{
- struct smbw_dir *dir;
- int ret;
-
- smbw_busy++;
-
- dir = smbw_dir(fd);
- if (dir) {
- smbw_busy--;
- return chdir(dir->path);
- }
-
- ret = real_fchdir(fd);
- if (ret == 0) {
- sys_getwd(smbw_cwd);
- }
-
- smbw_busy--;
- return ret;
-}
-
-/*****************************************************
-open a directory on the server
-*******************************************************/
-DIR *smbw_opendir(const char *fname)
-{
- int fd;
-
- smbw_busy++;
-
- fd = smbw_dir_open(fname);
-
- if (fd == -1) {
- smbw_busy--;
- return NULL;
- }
-
- smbw_busy--;
-
- return (DIR *)smbw_dir(fd);
-}
-
-/*****************************************************
-read one entry from a directory
-*******************************************************/
-struct dirent *smbw_readdir(DIR *dirp)
-{
- struct smbw_dir *d = (struct smbw_dir *)dirp;
- static union {
- char buf[DIRP_SIZE];
- struct dirent de;
- } dbuf;
-
- if (smbw_getdents(d->fd, &dbuf.de, DIRP_SIZE) > 0)
- return &dbuf.de;
-
- return NULL;
-}
-
-/*****************************************************
-close a DIR*
-*******************************************************/
-int smbw_closedir(DIR *dirp)
-{
- struct smbw_dir *d = (struct smbw_dir *)dirp;
- return smbw_close(d->fd);
-}
-
-/*****************************************************
-seek in a directory
-*******************************************************/
-void smbw_seekdir(DIR *dirp, off_t offset)
-{
- struct smbw_dir *d = (struct smbw_dir *)dirp;
- smbw_dir_lseek(d->fd,offset, SEEK_SET);
-}
-
-/*****************************************************
-current loc in a directory
-*******************************************************/
-off_t smbw_telldir(DIR *dirp)
-{
- struct smbw_dir *d = (struct smbw_dir *)dirp;
- return smbw_dir_lseek(d->fd,0,SEEK_CUR);
-}
diff --git a/source/smbwrapper/smbw_stat.c b/source/smbwrapper/smbw_stat.c
deleted file mode 100644
index 6effc9a71bc..00000000000
--- a/source/smbwrapper/smbw_stat.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper stat functions
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-extern int smbw_busy;
-
-/*****************************************************
-setup basic info in a stat structure
-*******************************************************/
-void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode)
-{
- st->st_mode = 0;
-
- if (IS_DOS_DIR(mode)) {
- st->st_mode = SMBW_DIR_MODE;
- } else {
- st->st_mode = SMBW_FILE_MODE;
- }
-
- if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR;
- if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP;
- if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH;
- if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR;
-
- st->st_size = size;
-#ifdef HAVE_STAT_ST_BLKSIZE
- st->st_blksize = 512;
-#endif
-#ifdef HAVE_STAT_ST_BLOCKS
- st->st_blocks = (size+511)/512;
-#endif
- st->st_uid = getuid();
- st->st_gid = getgid();
- if (IS_DOS_DIR(mode)) {
- st->st_nlink = 2;
- } else {
- st->st_nlink = 1;
- }
- if (st->st_ino == 0) {
- st->st_ino = smbw_inode(fname);
- }
-}
-
-
-/*****************************************************
-try to do a QPATHINFO and if that fails then do a getatr
-this is needed because win95 sometimes refuses the qpathinfo
-*******************************************************/
-BOOL smbw_getatr(struct smbw_server *srv, char *path,
- uint16 *mode, size_t *size,
- 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,
- &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, &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;
- }
- return False;
-}
-
-
-static struct print_job_info printjob;
-
-/*****************************************************
-gather info from a printjob listing
-*******************************************************/
-static void smbw_printjob_stat(struct print_job_info *job)
-{
- if (strcmp(job->name, printjob.name) == 0) {
- printjob = *job;
- }
-}
-
-/*****************************************************
-stat a printjob
-*******************************************************/
-int smbw_stat_printjob(struct smbw_server *srv,char *path,
- size_t *size, time_t *m_time)
-{
- if (path[0] == '\\') path++;
-
- ZERO_STRUCT(printjob);
-
- fstrcpy(printjob.name, path);
- cli_print_queue(&srv->cli, smbw_printjob_stat);
-
- if (size) {
- *size = printjob.size;
- }
- if (m_time) {
- *m_time = printjob.t;
- }
- return printjob.id;
-}
-
-
-/*****************************************************
-a wrapper for fstat()
-*******************************************************/
-int smbw_fstat(int fd, struct stat *st)
-{
- struct smbw_file *file;
- time_t c_time, a_time, m_time;
- SMB_OFF_T size;
- uint16 mode;
- SMB_INO_T ino = 0;
-
- smbw_busy++;
-
- ZERO_STRUCTP(st);
-
- file = smbw_file(fd);
- if (!file) {
- int ret = smbw_dir_fstat(fd, st);
- smbw_busy--;
- return ret;
- }
-
- if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
- &mode, &size, &c_time, &a_time, &m_time, NULL,
- &ino) &&
- !cli_getattrE(&file->srv->cli, file->f->cli_fd,
- &mode, &size, &c_time, &a_time, &m_time)) {
- errno = EINVAL;
- smbw_busy--;
- return -1;
- }
-
- st->st_ino = ino;
-
- smbw_setup_stat(st, file->f->fname, size, mode);
-
- st->st_atime = a_time;
- st->st_ctime = c_time;
- st->st_mtime = m_time;
- st->st_dev = file->srv->dev;
-
- smbw_busy--;
- return 0;
-}
-
-
-/*****************************************************
-a wrapper for stat()
-*******************************************************/
-int smbw_stat(const char *fname, struct stat *st)
-{
- struct smbw_server *srv;
- fstring server, share;
- pstring path;
- time_t m_time=0, a_time=0, c_time=0;
- size_t size=0;
- uint16 mode=0;
- SMB_INO_T ino = 0;
- int result = 0;
-
- ZERO_STRUCTP(st);
-
- if (!fname) {
- errno = EINVAL;
- return -1;
- }
-
- DEBUG(4,("stat(%s)\n", fname));
-
- smbw_init();
-
- smbw_busy++;
-
- /* work out what server they are after */
- smbw_parse_path(fname, server, share, path);
-
- /* get a connection to the server */
- srv = smbw_server(server, share);
- if (!srv) {
-
- /* For shares we aren't allowed to connect to, or no master
- browser found, return an empty directory */
-
- if ((server[0] && share[0] && !path[0] && errno == EACCES) ||
- (!path[0] && errno == ENOENT)) {
- mode = aDIR | aRONLY;
- smbw_setup_stat(st, path, size, mode);
- goto done;
- }
-
- /* smbw_server sets errno */
- result = -1;
- goto done;
- }
-
- DEBUG(4,("smbw_stat\n"));
-
- if (strncmp(srv->cli.dev,"IPC",3) == 0) {
- mode = aDIR | aRONLY;
- } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
- if (strcmp(path,"\\") == 0) {
- mode = aDIR | aRONLY;
- } else {
- mode = aRONLY;
- smbw_stat_printjob(srv, path, &size, &m_time);
- c_time = a_time = m_time;
- }
- } else {
- if (!smbw_getatr(srv, path,
- &mode, &size, &c_time, &a_time, &m_time,
- &ino)) {
- errno = smbw_errno(&srv->cli);
- result = -1;
- goto done;
- }
- }
-
- st->st_ino = ino;
-
- smbw_setup_stat(st, path, size, mode);
-
- st->st_atime = a_time;
- st->st_ctime = c_time;
- st->st_mtime = m_time;
- st->st_dev = srv->dev;
-
- done:
- smbw_busy--;
- return result;
-}
diff --git a/source/smbwrapper/wrapped.c b/source/smbwrapper/wrapped.c
deleted file mode 100644
index e1bbccd836b..00000000000
--- a/source/smbwrapper/wrapped.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB wrapper functions
- Copyright (C) Andrew Tridgell 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* NOTE: This file WILL produce compiler warnings. They are unavoidable
-
- Do not try and get rid of them by including other include files or
- by including includes.h or proto.h or you will break portability.
- */
-
-#include "config.h"
-#include <sys/types.h>
-#include <errno.h>
-#include "realcalls.h"
-
-#ifndef NULL
-# define NULL ((void *)0)
-#endif
-
- int open(const char *name, int flags, mode_t mode)
-{
- if (smbw_path(name)) {
- return smbw_open(name, flags, mode);
- }
-
- return real_open(name, flags, mode);
-}
-
-#ifdef HAVE__OPEN
- int _open(const char *name, int flags, mode_t mode)
-{
- return open(name, flags, mode);
-}
-#elif HAVE___OPEN
- int __open(char *name, int flags, mode_t mode)
-{
- return open(name, flags, mode);
-}
-#endif
-
-
-#ifdef HAVE_OPEN64
- int open64(const char *name, int flags, mode_t mode)
-{
- if (smbw_path(name)) {
- return smbw_open(name, flags, mode);
- }
-
- return real_open64(name, flags, mode);
-}
-#endif
-
-#ifndef NO_OPEN64_ALIAS
-#ifdef HAVE__OPEN64
- int _open64(const char *name, int flags, mode_t mode)
-{
- return open64(name, flags, mode);
-}
-#elif HAVE___OPEN64
- int __open64(const char *name, int flags, mode_t mode)
-{
- return open64(name, flags, mode);
-}
-#endif
-#endif
-
-#ifdef HAVE_PREAD
- ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
-{
- if (smbw_fd(fd)) {
- return smbw_pread(fd, buf, size, ofs);
- }
-
- return real_pread(fd, buf, size, ofs);
-}
-#endif
-
-#if 0 && defined(HAVE_PREAD64) && defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT)
- ssize_t pread64(int fd, void *buf, size_t size, off64_t ofs)
-{
- if (smbw_fd(fd)) {
- return smbw_pread(fd, buf, size, ofs);
- }
-
- return real_pread64(fd, buf, size, ofs);
-}
-#endif
-
-#ifdef HAVE_PWRITE
- ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
-{
- if (smbw_fd(fd)) {
- return smbw_pwrite(fd, buf, size, ofs);
- }
-
- return real_pwrite(fd, buf, size, ofs);
-}
-#endif
-
-#if 0 && defined(HAVE_PWRITE64) && defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT)
- ssize_t pwrite64(int fd, const void *buf, size_t size, off64_t ofs)
-{
- if (smbw_fd(fd)) {
- return smbw_pwrite(fd, buf, size, ofs);
- }
-
- return real_pwrite64(fd, buf, size, ofs);
-}
-#endif
-
-
- int chdir(const char *name)
-{
- return smbw_chdir(name);
-}
-
-#ifdef HAVE___CHDIR
- int __chdir(const char *name)
-{
- return chdir(name);
-}
-#elif HAVE__CHDIR
- int _chdir(const char *name)
-{
- return chdir(name);
-}
-#endif
-
-
- int close(int fd)
-{
- if (smbw_fd(fd)) {
- return smbw_close(fd);
- }
- if (smbw_local_fd(fd)) {
- errno = EBADF;
- return -1;
- }
-
- return real_close(fd);
-}
-
-#ifdef HAVE___CLOSE
- int __close(int fd)
-{
- return close(fd);
-}
-#elif HAVE__CLOSE
- int _close(int fd)
-{
- return close(fd);
-}
-#endif
-
-
- int fchdir(int fd)
-{
- return smbw_fchdir(fd);
-}
-
-#ifdef HAVE___FCHDIR
- int __fchdir(int fd)
-{
- return fchdir(fd);
-}
-#elif HAVE__FCHDIR
- int _fchdir(int fd)
-{
- return fchdir(fd);
-}
-#endif
-
-
- int fcntl(int fd, int cmd, long arg)
-{
- if (smbw_fd(fd)) {
- return smbw_fcntl(fd, cmd, arg);
- }
-
- return real_fcntl(fd, cmd, arg);
-}
-
-
-#ifdef HAVE___FCNTL
- int __fcntl(int fd, int cmd, long arg)
-{
- return fcntl(fd, cmd, arg);
-}
-#elif HAVE__FCNTL
- int _fcntl(int fd, int cmd, long arg)
-{
- return fcntl(fd, cmd, arg);
-}
-#endif
-
-
-
-#ifdef real_getdents
- int getdents(int fd, void *dirp, unsigned int count)
-{
- if (smbw_fd(fd)) {
- return smbw_getdents(fd, dirp, count);
- }
-
- return real_getdents(fd, dirp, count);
-}
-#endif
-
-#ifdef HAVE___GETDENTS
- int __getdents(int fd, void *dirp, unsigned int count)
-{
- return getdents(fd, dirp, count);
-}
-#elif HAVE__GETDENTS
- int _getdents(int fd, void *dirp, unsigned int count)
-{
- return getdents(fd, dirp, count);
-}
-#endif
-
-
- off_t lseek(int fd, off_t offset, int whence)
-{
- if (smbw_fd(fd)) {
- return smbw_lseek(fd, offset, whence);
- }
-
- return real_lseek(fd, offset, whence);
-}
-
-#ifdef HAVE___LSEEK
- off_t __lseek(int fd, off_t offset, int whence)
-{
- return lseek(fd, offset, whence);
-}
-#elif HAVE__LSEEK
- off_t _lseek(int fd, off_t offset, int whence)
-{
- return lseek(fd, offset, whence);
-}
-#endif
-
-
- ssize_t read(int fd, void *buf, size_t count)
-{
- if (smbw_fd(fd)) {
- return smbw_read(fd, buf, count);
- }
-
- return real_read(fd, buf, count);
-}
-
-#ifdef HAVE___READ
- ssize_t __read(int fd, void *buf, size_t count)
-{
- return read(fd, buf, count);
-}
-#elif HAVE__READ
- ssize_t _read(int fd, void *buf, size_t count)
-{
- return read(fd, buf, count);
-}
-#endif
-
-
- ssize_t write(int fd, const void *buf, size_t count)
-{
- if (smbw_fd(fd)) {
- return smbw_write(fd, buf, count);
- }
-
- return real_write(fd, buf, count);
-}
-
-#ifdef HAVE___WRITE
- ssize_t __write(int fd, const void *buf, size_t count)
-{
- return write(fd, buf, count);
-}
-#elif HAVE__WRITE
- ssize_t _write(int fd, const void *buf, size_t count)
-{
- return write(fd, buf, count);
-}
-#endif
-
-
-
- int access(const char *name, int mode)
-{
- if (smbw_path(name)) {
- return smbw_access(name, mode);
- }
-
- return real_access(name, mode);
-}
-
-
-
- int chmod(const char *name,mode_t mode)
-{
- if (smbw_path(name)) {
- return smbw_chmod(name, mode);
- }
-
- return real_chmod(name, mode);
-}
-
-
-
- int chown(const char *name,uid_t owner, gid_t group)
-{
- if (smbw_path(name)) {
- return smbw_chown(name, owner, group);
- }
-
- return real_chown(name, owner, group);
-}
-
-
- char *getcwd(char *buf, size_t size)
-{
- return (char *)smbw_getcwd(buf, size);
-}
-
-
-
-
- int mkdir(const char *name, mode_t mode)
-{
- if (smbw_path(name)) {
- return smbw_mkdir(name, mode);
- }
-
- return real_mkdir(name, mode);
-}
-
-
-#if HAVE___FXSTAT
- int __fxstat(int vers, int fd, void *st)
-{
- double xx[32];
- int ret;
-
- if (smbw_fd(fd)) {
- return smbw_fstat(fd, st);
- }
-
- ret = real_fstat(fd, xx);
- xstat_convert(vers, st, xx);
- return ret;
-}
-#endif
-
-#if HAVE___XSTAT
- int __xstat(int vers, const char *name, void *st)
-{
- double xx[32];
- int ret;
-
- if (smbw_path(name)) {
- return smbw_stat(name, st);
- }
-
- ret = real_stat(name, xx);
- xstat_convert(vers, st, xx);
- return ret;
-}
-#endif
-
-
-#if HAVE___LXSTAT
- int __lxstat(int vers, const char *name, void *st)
-{
- double xx[32];
- int ret;
-
- if (smbw_path(name)) {
- return smbw_stat(name, st);
- }
-
- ret = real_lstat(name, xx);
- xstat_convert(vers, st, xx);
- return ret;
-}
-#endif
-
-
- int stat(const char *name, void *st)
-{
-#if HAVE___XSTAT
- return __xstat(0, name, st);
-#else
- if (smbw_path(name)) {
- return smbw_stat(name, st);
- }
- return real_stat(name, st);
-#endif
-}
-
- int lstat(const char *name, void *st)
-{
-#if HAVE___LXSTAT
- return __lxstat(0, name, st);
-#else
- if (smbw_path(name)) {
- return smbw_stat(name, st);
- }
- return real_lstat(name, st);
-#endif
-}
-
- int fstat(int fd, void *st)
-{
-#if HAVE___LXSTAT
- return __fxstat(0, fd, st);
-#else
- if (smbw_fd(fd)) {
- return smbw_fstat(fd, st);
- }
- return real_fstat(fd, st);
-#endif
-}
-
-
- int unlink(const char *name)
-{
- if (smbw_path(name)) {
- return smbw_unlink(name);
- }
-
- return real_unlink(name);
-}
-
-
-#ifdef HAVE_UTIME
- int utime(const char *name,void *tvp)
-{
- if (smbw_path(name)) {
- return smbw_utime(name, tvp);
- }
-
- return real_utime(name, tvp);
-}
-#endif
-
-#ifdef HAVE_UTIMES
- int utimes(const char *name, const struct timeval *tvp)
-{
- if (smbw_path(name)) {
- return smbw_utimes(name, tvp);
- }
-
- return real_utimes(name, tvp);
-}
-#endif
-
- int readlink(const char *path, char *buf, size_t bufsize)
-{
- if (smbw_path(path)) {
- return smbw_readlink(path, buf, bufsize);
- }
-
- return real_readlink(path, buf, bufsize);
-}
-
-
- int rename(const char *oldname,const char *newname)
-{
- int p1, p2;
- p1 = smbw_path(oldname);
- p2 = smbw_path(newname);
- if (p1 ^ p2) {
- /* can't cross filesystem boundaries */
- errno = EXDEV;
- return -1;
- }
- if (p1 && p2) {
- return smbw_rename(oldname, newname);
- }
-
- return real_rename(oldname, newname);
-}
-
- int rmdir(const char *name)
-{
- if (smbw_path(name)) {
- return smbw_rmdir(name);
- }
-
- return real_rmdir(name);
-}
-
-
- int symlink(const char *topath,const char *frompath)
-{
- int p1, p2;
- p1 = smbw_path(topath);
- p2 = smbw_path(frompath);
- if (p1 || p2) {
- /* can't handle symlinks */
- errno = EPERM;
- return -1;
- }
-
- return real_symlink(topath, frompath);
-}
-
- int dup(int fd)
-{
- if (smbw_fd(fd)) {
- return smbw_dup(fd);
- }
-
- return real_dup(fd);
-}
-
- int dup2(int oldfd, int newfd)
-{
- if (smbw_fd(newfd)) {
- close(newfd);
- }
-
- if (smbw_fd(oldfd)) {
- return smbw_dup2(oldfd, newfd);
- }
-
- return real_dup2(oldfd, newfd);
-}
-
-#ifdef real_opendir
- void *opendir(const char *name)
-{
- if (smbw_path(name)) {
- return (void *)smbw_opendir(name);
- }
-
- return (void *)real_opendir(name);
-}
-#endif
-
-#ifdef real_readdir
- void *readdir(void *dir)
-{
- if (smbw_dirp(dir)) {
- return (void *)smbw_readdir(dir);
- }
-
- return (void *)real_readdir(dir);
-}
-#endif
-
-#ifdef real_closedir
- int closedir(void *dir)
-{
- if (smbw_dirp(dir)) {
- return smbw_closedir(dir);
- }
-
- return real_closedir(dir);
-}
-#endif
-
-#ifdef real_telldir
- off_t telldir(void *dir)
-{
- if (smbw_dirp(dir)) {
- return smbw_telldir(dir);
- }
-
- return real_telldir(dir);
-}
-#endif
-
-#ifdef real_seekdir
- int seekdir(void *dir, off_t offset)
-{
- if (smbw_dirp(dir)) {
- smbw_seekdir(dir, offset);
- return 0;
- }
-
- real_seekdir(dir, offset);
- return 0;
-}
-#endif
-
-
-#ifndef NO_ACL_WRAPPER
- int acl(char *pathp, int cmd, int nentries, void *aclbufp)
-{
- if (smbw_path(pathp)) {
- return smbw_acl(pathp, cmd, nentries, aclbufp);
- }
-
- return real_acl(pathp, cmd, nentries, aclbufp);
-}
-#endif
-
-#ifndef NO_FACL_WRAPPER
- int facl(int fd, int cmd, int nentries, void *aclbufp)
-{
- if (smbw_fd(fd)) {
- return smbw_facl(fd, cmd, nentries, aclbufp);
- }
-
- return real_facl(fd, cmd, nentries, aclbufp);
-}
-#endif
-
- int creat(const char *path, mode_t mode)
-{
- extern int creat_bits;
- return open(path, creat_bits, mode);
-}
-
-#ifdef HAVE_CREAT64
- int creat64(const char *path, mode_t mode)
-{
- extern int creat_bits;
- return open64(path, creat_bits, mode);
-}
-#endif
-
-#ifdef HAVE_STAT64
- int stat64(const char *name, void *st64)
-{
- if (smbw_path(name)) {
- double xx[32];
- int ret = stat(name, xx);
- stat64_convert(xx, st64);
- return ret;
- }
- return real_stat64(name, st64);
-}
-
- int fstat64(int fd, void *st64)
-{
- if (smbw_fd(fd)) {
- double xx[32];
- int ret = fstat(fd, xx);
- stat64_convert(xx, st64);
- return ret;
- }
- return real_fstat64(fd, st64);
-}
-
- int lstat64(const char *name, void *st64)
-{
- if (smbw_path(name)) {
- double xx[32];
- int ret = lstat(name, xx);
- stat64_convert(xx, st64);
- return ret;
- }
- return real_lstat64(name, st64);
-}
-#endif
-
-#ifdef HAVE_LLSEEK
- offset_t llseek(int fd, offset_t ofs, int whence)
-{
- if (smbw_fd(fd)) {
- return lseek(fd, ofs, whence);
- }
- return real_llseek(fd, ofs, whence);
-}
-#endif
-
-#ifdef HAVE_READDIR64
- void *readdir64(void *dir)
-{
- if (smbw_dirp(dir)) {
- static double xx[70];
- void *d;
- d = (void *)readdir(dir);
- if (!d) return NULL;
- dirent64_convert(d, xx);
- return xx;
- }
- return (void *)real_readdir64(dir);
-}
-#endif
-
- int fork(void)
-{
- return smbw_fork();
-}
-
diff --git a/source/tdb/Makefile b/source/tdb/Makefile
deleted file mode 100644
index 92bc33a661e..00000000000
--- a/source/tdb/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Makefile for tdb directory
-#
-
-CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1
-CC = gcc
-
-ADMINPROGS = tdbdump tdbbackup
-PROGS = tdbtest tdbtool tdbtorture
-TDB_OBJ = tdb.o spinlock.o tdbback.o
-
-default: $(PROGS)
-
-admintools: $(ADMINPROGS)
-
-tdbtest: tdbtest.o $(TDB_OBJ)
- $(CC) $(CFLAGS) -o tdbtest tdbtest.o $(TDB_OBJ) -lgdbm
-
-tdbtool: tdbtool.o $(TDB_OBJ)
- $(CC) $(CFLAGS) -o tdbtool tdbtool.o $(TDB_OBJ)
-
-tdbtorture: tdbtorture.o $(TDB_OBJ)
- $(CC) $(CFLAGS) -o tdbtorture tdbtorture.o $(TDB_OBJ)
-
-tdbdump: tdbdump.o $(TDB_OBJ)
- $(CC) $(CFLAGS) -o tdbdump tdbdump.o $(TDB_OBJ)
-
-tdbbackup: tdbbackup.o $(TDB_OBJ)
- $(CC) $(CFLAGS) -o tdbbackup tdbbackup.o $(TDB_OBJ)
-
-clean:
- rm -f $(PROGS) *.o *~ *% core test.db test.tdb test.gdbm
diff --git a/source/tdb/Makefile.in b/source/tdb/Makefile.in
new file mode 100644
index 00000000000..455a6e52ce4
--- /dev/null
+++ b/source/tdb/Makefile.in
@@ -0,0 +1,89 @@
+#!gmake
+#
+# Makefile for tdb directory
+#
+
+CC = @CC@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+VPATH = @srcdir@:@libreplacedir@
+srcdir = @srcdir@
+builddir = @builddir@
+CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/include -Iinclude -I../include -I@libreplacedir@
+CFLAGS = $(CPPFLAGS) @CFLAGS@
+LDFLAGS = @LDFLAGS@
+EXEEXT = @EXEEXT@
+
+.PHONY: test
+
+PROGS = bin/tdbtool$(EXEEXT) bin/tdbtorture$(EXEEXT)
+PROGS_NOINSTALL = bin/tdbtest$(EXEEXT) bin/tdbdump$(EXEEXT) bin/tdbbackup$(EXEEXT)
+ALL_PROGS = $(PROGS) $(PROGS_NOINSTALL)
+
+TDB_OBJ = @TDBOBJ@
+
+DIRS = bin common tools
+
+all: showflags dirs $(PROGS)
+
+showflags:
+ @echo 'tdb will be compiled with flags:'
+ @echo ' CFLAGS = $(CFLAGS)'
+ @echo ' CPPFLAGS = $(CPPFLAGS)'
+ @echo ' LDFLAGS = $(LDFLAGS)'
+ @echo ' LIBS = $(LIBS)'
+
+.c.o:
+ @echo Compiling $*.c
+ @mkdir -p `dirname $@`
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+dirs:
+ @mkdir -p $(DIRS)
+
+install: all
+ mkdir -p $(bindir)
+ mkdir -p $(includedir)
+ mkdir -p $(libdir)
+ mkdir -p $(libdir)/pkgconfig
+ cp $(PROGS) $(bindir)
+ cp $(srcdir)/include/tdb.h $(includedir)
+ cp tdb.pc $(libdir)/pkgconfig
+
+libtdb.a: $(TDB_OBJ)
+ ar -rv libtdb.a $(TDB_OBJ)
+
+bin/tdbtest$(EXEEXT): tools/tdbtest.o libtdb.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o bin/tdbtest tools/tdbtest.o -L. -ltdb -lgdbm
+
+bin/tdbtool$(EXEEXT): tools/tdbtool.o libtdb.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o bin/tdbtool tools/tdbtool.o -L. -ltdb
+
+bin/tdbtorture$(EXEEXT): tools/tdbtorture.o libtdb.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o bin/tdbtorture tools/tdbtorture.o -L. -ltdb
+
+bin/tdbdump$(EXEEXT): tools/tdbdump.o libtdb.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o bin/tdbdump tools/tdbdump.o -L. -ltdb
+
+bin/tdbbackup$(EXEEXT): tools/tdbbackup.o libtdb.a
+ $(CC) $(CFLAGS) $(LDFLAGS) -o bin/tdbbackup tools/tdbbackup.o -L. -ltdb
+
+test: bin/tdbtorture$(EXEEXT)
+ bin/tdbtorture$(EXEEXT)
+
+installcheck: test install
+
+clean:
+ rm -f $(ALL_PROGS) *.o *.a common/*.o tools/*.o tdb.pc
+ rm -f test.db test.tdb torture.tdb test.gdbm
+
+distclean: clean
+ rm -f *~ */*~
+ rm -f config.log config.status include/config.h config.cache
+ rm -f Makefile
+
+realdistclean: distclean
+ rm -f configure include/config.h.in
diff --git a/source/tdb/aclocal.m4 b/source/tdb/aclocal.m4
new file mode 100644
index 00000000000..5605e476bab
--- /dev/null
+++ b/source/tdb/aclocal.m4
@@ -0,0 +1 @@
+m4_include(libreplace.m4)
diff --git a/source/tdb/autogen.sh b/source/tdb/autogen.sh
new file mode 100755
index 00000000000..1691689e10c
--- /dev/null
+++ b/source/tdb/autogen.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f configure config.h.in
+
+IPATHS="-I libreplace -I lib/replace -I ../libreplace -I ../replace -I ../lib/replace"
+autoconf $IPATHS || exit 1
+autoheader $IPATHS || exit 1
+
+rm -rf autom4te.cache
+
+echo "Now run ./configure and then make."
+exit 0
+
diff --git a/source/tdb/common/dump.c b/source/tdb/common/dump.c
new file mode 100644
index 00000000000..3f5c2c87f5b
--- /dev/null
+++ b/source/tdb/common/dump.c
@@ -0,0 +1,138 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
+ tdb_off_t offset)
+{
+ struct list_struct rec;
+ tdb_off_t tailer_ofs, tailer;
+
+ if (tdb->methods->tdb_read(tdb, offset, (char *)&rec,
+ sizeof(rec), DOCONV()) == -1) {
+ printf("ERROR: failed to read record at %u\n", offset);
+ return 0;
+ }
+
+ printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d "
+ "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
+ hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len,
+ rec.full_hash, rec.magic);
+
+ tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t);
+
+ if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) {
+ printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
+ return rec.next;
+ }
+
+ if (tailer != rec.rec_len + sizeof(rec)) {
+ printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
+ (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec)));
+ }
+ return rec.next;
+}
+
+static int tdb_dump_chain(struct tdb_context *tdb, int i)
+{
+ tdb_off_t rec_ptr, top;
+
+ top = TDB_HASH_TOP(i);
+
+ if (tdb_lock(tdb, i, F_WRLCK) != 0)
+ return -1;
+
+ if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
+ return tdb_unlock(tdb, i, F_WRLCK);
+
+ if (rec_ptr)
+ printf("hash=%d\n", i);
+
+ while (rec_ptr) {
+ rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
+ }
+
+ return tdb_unlock(tdb, i, F_WRLCK);
+}
+
+void tdb_dump_all(struct tdb_context *tdb)
+{
+ int i;
+ for (i=0;i<tdb->header.hash_size;i++) {
+ tdb_dump_chain(tdb, i);
+ }
+ printf("freelist:\n");
+ tdb_dump_chain(tdb, -1);
+}
+
+int tdb_printfreelist(struct tdb_context *tdb)
+{
+ int ret;
+ long total_free = 0;
+ tdb_off_t offset, rec_ptr;
+ struct list_struct rec;
+
+ if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
+ return ret;
+
+ offset = FREELIST_TOP;
+
+ /* read in the freelist top */
+ if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) {
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return 0;
+ }
+
+ printf("freelist top=[0x%08x]\n", rec_ptr );
+ while (rec_ptr) {
+ if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec,
+ sizeof(rec), DOCONV()) == -1) {
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return -1;
+ }
+
+ if (rec.magic != TDB_FREE_MAGIC) {
+ printf("bad magic 0x%08x in free list\n", rec.magic);
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return -1;
+ }
+
+ printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n",
+ rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len);
+ total_free += rec.rec_len;
+
+ /* move to the next record */
+ rec_ptr = rec.next;
+ }
+ printf("total rec_len = [0x%08x (%d)]\n", (int)total_free,
+ (int)total_free);
+
+ return tdb_unlock(tdb, -1, F_WRLCK);
+}
+
diff --git a/source/tdb/common/error.c b/source/tdb/common/error.c
new file mode 100644
index 00000000000..4cf33a29ab2
--- /dev/null
+++ b/source/tdb/common/error.c
@@ -0,0 +1,58 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+enum TDB_ERROR tdb_error(struct tdb_context *tdb)
+{
+ return tdb->ecode;
+}
+
+static struct tdb_errname {
+ enum TDB_ERROR ecode; const char *estring;
+} emap[] = { {TDB_SUCCESS, "Success"},
+ {TDB_ERR_CORRUPT, "Corrupt database"},
+ {TDB_ERR_IO, "IO Error"},
+ {TDB_ERR_LOCK, "Locking error"},
+ {TDB_ERR_OOM, "Out of memory"},
+ {TDB_ERR_EXISTS, "Record exists"},
+ {TDB_ERR_NOLOCK, "Lock exists on other keys"},
+ {TDB_ERR_EINVAL, "Invalid parameter"},
+ {TDB_ERR_NOEXIST, "Record does not exist"},
+ {TDB_ERR_RDONLY, "write not permitted"} };
+
+/* Error string for the last tdb error */
+const char *tdb_errorstr(struct tdb_context *tdb)
+{
+ u32 i;
+ for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++)
+ if (tdb->ecode == emap[i].ecode)
+ return emap[i].estring;
+ return "Invalid error code";
+}
+
diff --git a/source/tdb/common/freelist.c b/source/tdb/common/freelist.c
new file mode 100644
index 00000000000..0efe47f8798
--- /dev/null
+++ b/source/tdb/common/freelist.c
@@ -0,0 +1,331 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/* read a freelist record and check for simple errors */
+int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
+{
+ if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
+ return -1;
+
+ if (rec->magic == TDB_MAGIC) {
+ /* this happens when a app is showdown while deleting a record - we should
+ not completely fail when this happens */
+ TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
+ rec->magic, off));
+ rec->magic = TDB_FREE_MAGIC;
+ if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
+ return -1;
+ }
+
+ if (rec->magic != TDB_FREE_MAGIC) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_CORRUPT;
+ TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read bad magic 0x%x at offset=%d\n",
+ rec->magic, off));
+ return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+ }
+ if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
+ return -1;
+ return 0;
+}
+
+
+
+/* Remove an element from the freelist. Must have alloc lock. */
+static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next)
+{
+ tdb_off_t last_ptr, i;
+
+ /* read in the freelist top */
+ last_ptr = FREELIST_TOP;
+ while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
+ if (i == off) {
+ /* We've found it! */
+ return tdb_ofs_write(tdb, last_ptr, &next);
+ }
+ /* Follow chain (next offset is at start of record) */
+ last_ptr = i;
+ }
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
+ return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+}
+
+
+/* update a record tailer (must hold allocation lock) */
+static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
+ const struct list_struct *rec)
+{
+ tdb_off_t totalsize;
+
+ /* Offset of tailer from record header */
+ totalsize = sizeof(*rec) + rec->rec_len;
+ return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t),
+ &totalsize);
+}
+
+/* Add an element into the freelist. Merge adjacent records if
+ neccessary. */
+int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+ tdb_off_t right, left;
+
+ /* Allocation and tailer lock */
+ if (tdb_lock(tdb, -1, F_WRLCK) != 0)
+ return -1;
+
+ /* set an initial tailer, so if we fail we don't leave a bogus record */
+ if (update_tailer(tdb, offset, rec) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n"));
+ goto fail;
+ }
+
+ /* Look right first (I'm an Australian, dammit) */
+ right = offset + sizeof(*rec) + rec->rec_len;
+ if (right + sizeof(*rec) <= tdb->map_size) {
+ struct list_struct r;
+
+ if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right));
+ goto left;
+ }
+
+ /* If it's free, expand to include it. */
+ if (r.magic == TDB_FREE_MAGIC) {
+ if (remove_from_freelist(tdb, right, r.next) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right));
+ goto left;
+ }
+ rec->rec_len += sizeof(r) + r.rec_len;
+ }
+ }
+
+left:
+ /* Look left */
+ left = offset - sizeof(tdb_off_t);
+ if (left > TDB_DATA_START(tdb->header.hash_size)) {
+ struct list_struct l;
+ tdb_off_t leftsize;
+
+ /* Read in tailer and jump back to header */
+ if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
+ goto update;
+ }
+
+ /* it could be uninitialised data */
+ if (leftsize == 0 || leftsize == TDB_PAD_U32) {
+ goto update;
+ }
+
+ left = offset - leftsize;
+
+ /* Now read in record */
+ if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
+ goto update;
+ }
+
+ /* If it's free, expand to include it. */
+ if (l.magic == TDB_FREE_MAGIC) {
+ if (remove_from_freelist(tdb, left, l.next) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left));
+ goto update;
+ } else {
+ offset = left;
+ rec->rec_len += leftsize;
+ }
+ }
+ }
+
+update:
+ if (update_tailer(tdb, offset, rec) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
+ goto fail;
+ }
+
+ /* Now, prepend to free list */
+ rec->magic = TDB_FREE_MAGIC;
+
+ if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
+ tdb_rec_write(tdb, offset, rec) == -1 ||
+ tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset));
+ goto fail;
+ }
+
+ /* And we're done. */
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return 0;
+
+ fail:
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return -1;
+}
+
+
+/*
+ the core of tdb_allocate - called when we have decided which
+ free list entry to use
+ */
+static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr,
+ struct list_struct *rec, tdb_off_t last_ptr)
+{
+ struct list_struct newrec;
+ tdb_off_t newrec_ptr;
+
+ memset(&newrec, '\0', sizeof(newrec));
+
+ /* found it - now possibly split it up */
+ if (rec->rec_len > length + MIN_REC_SIZE) {
+ /* Length of left piece */
+ length = TDB_ALIGN(length, TDB_ALIGNMENT);
+
+ /* Right piece to go on free list */
+ newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
+ newrec_ptr = rec_ptr + sizeof(*rec) + length;
+
+ /* And left record is shortened */
+ rec->rec_len = length;
+ } else {
+ newrec_ptr = 0;
+ }
+
+ /* Remove allocated record from the free list */
+ if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
+ return 0;
+ }
+
+ /* Update header: do this before we drop alloc
+ lock, otherwise tdb_free() might try to
+ merge with us, thinking we're free.
+ (Thanks Jeremy Allison). */
+ rec->magic = TDB_MAGIC;
+ if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
+ return 0;
+ }
+
+ /* Did we create new block? */
+ if (newrec_ptr) {
+ /* Update allocated record tailer (we
+ shortened it). */
+ if (update_tailer(tdb, rec_ptr, rec) == -1) {
+ return 0;
+ }
+
+ /* Free new record */
+ if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
+ return 0;
+ }
+ }
+
+ /* all done - return the new record offset */
+ return rec_ptr;
+}
+
+/* allocate some space from the free list. The offset returned points
+ to a unconnected list_struct within the database with room for at
+ least length bytes of total data
+
+ 0 is returned if the space could not be allocated
+ */
+tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec)
+{
+ tdb_off_t rec_ptr, last_ptr, newrec_ptr;
+ struct {
+ tdb_off_t rec_ptr, last_ptr;
+ tdb_len_t rec_len;
+ } bestfit;
+
+ if (tdb_lock(tdb, -1, F_WRLCK) == -1)
+ return 0;
+
+ /* Extra bytes required for tailer */
+ length += sizeof(tdb_off_t);
+
+ again:
+ last_ptr = FREELIST_TOP;
+
+ /* read in the freelist top */
+ if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
+ goto fail;
+
+ bestfit.rec_ptr = 0;
+ bestfit.last_ptr = 0;
+ bestfit.rec_len = 0;
+
+ /*
+ this is a best fit allocation strategy. Originally we used
+ a first fit strategy, but it suffered from massive fragmentation
+ issues when faced with a slowly increasing record size.
+ */
+ while (rec_ptr) {
+ if (rec_free_read(tdb, rec_ptr, rec) == -1) {
+ goto fail;
+ }
+
+ if (rec->rec_len >= length) {
+ if (bestfit.rec_ptr == 0 ||
+ rec->rec_len < bestfit.rec_len) {
+ bestfit.rec_len = rec->rec_len;
+ bestfit.rec_ptr = rec_ptr;
+ bestfit.last_ptr = last_ptr;
+ /* consider a fit to be good enough if
+ we aren't wasting more than half
+ the space */
+ if (bestfit.rec_len < 2*length) {
+ break;
+ }
+ }
+ }
+
+ /* move to the next record */
+ last_ptr = rec_ptr;
+ rec_ptr = rec->next;
+ }
+
+ if (bestfit.rec_ptr != 0) {
+ if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
+ goto fail;
+ }
+
+ newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr);
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return newrec_ptr;
+ }
+
+ /* we didn't find enough space. See if we can expand the
+ database and if we can then try again */
+ if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
+ goto again;
+ fail:
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return 0;
+}
+
diff --git a/source/tdb/common/freelistcheck.c b/source/tdb/common/freelistcheck.c
new file mode 100644
index 00000000000..3f79a016b86
--- /dev/null
+++ b/source/tdb/common/freelistcheck.c
@@ -0,0 +1,108 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Jeremy Allison 2006
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/* Check the freelist is good and contains no loops.
+ Very memory intensive - only do this as a consistency
+ checker. Heh heh - uses an in memory tdb as the storage
+ for the "seen" record list. For some reason this strikes
+ me as extremely clever as I don't have to write another tree
+ data structure implementation :-).
+ */
+
+static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr)
+{
+ TDB_DATA key, data;
+
+ memset(&data, '\0', sizeof(data));
+ key.dptr = (char *)&rec_ptr;
+ key.dsize = sizeof(rec_ptr);
+ return tdb_store(mem_tdb, key, data, TDB_INSERT);
+}
+
+int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
+{
+ struct tdb_context *mem_tdb = NULL;
+ struct list_struct rec;
+ tdb_off_t rec_ptr, last_ptr;
+ int ret = -1;
+
+ *pnum_entries = 0;
+
+ mem_tdb = tdb_open("flval", tdb->header.hash_size,
+ TDB_INTERNAL, O_RDWR, 0600);
+ if (!mem_tdb) {
+ return -1;
+ }
+
+ if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+ tdb_close(mem_tdb);
+ return 0;
+ }
+
+ last_ptr = FREELIST_TOP;
+
+ /* Store the FREELIST_TOP record. */
+ if (seen_insert(mem_tdb, last_ptr) == -1) {
+ ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+ goto fail;
+ }
+
+ /* read in the freelist top */
+ if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) {
+ goto fail;
+ }
+
+ while (rec_ptr) {
+
+ /* If we can't store this record (we've seen it
+ before) then the free list has a loop and must
+ be corrupt. */
+
+ if (seen_insert(mem_tdb, rec_ptr)) {
+ ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+ goto fail;
+ }
+
+ if (rec_free_read(tdb, rec_ptr, &rec) == -1) {
+ goto fail;
+ }
+
+ /* move to the next record */
+ last_ptr = rec_ptr;
+ rec_ptr = rec.next;
+ *pnum_entries += 1;
+ }
+
+ ret = 0;
+
+ fail:
+
+ tdb_close(mem_tdb);
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return ret;
+}
diff --git a/source/tdb/common/io.c b/source/tdb/common/io.c
new file mode 100644
index 00000000000..9a8e270dcc6
--- /dev/null
+++ b/source/tdb/common/io.c
@@ -0,0 +1,427 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include "tdb_private.h"
+
+/* check for an out of bounds access - if it is out of bounds then
+ see if the database has been expanded by someone else and expand
+ if necessary
+ note that "len" is the minimum length needed for the db
+*/
+static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
+{
+ struct stat st;
+ if (len <= tdb->map_size)
+ return 0;
+ if (tdb->flags & TDB_INTERNAL) {
+ if (!probe) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n",
+ (int)len, (int)tdb->map_size));
+ }
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ }
+
+ if (fstat(tdb->fd, &st) == -1) {
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ }
+
+ if (st.st_size < (size_t)len) {
+ if (!probe) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n",
+ (int)len, (int)st.st_size));
+ }
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ }
+
+ /* Unmap, update size, remap */
+ if (tdb_munmap(tdb) == -1)
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ tdb->map_size = st.st_size;
+ tdb_mmap(tdb);
+ return 0;
+}
+
+/* write a lump of data at a specified offset */
+static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
+ const void *buf, tdb_len_t len)
+{
+ if (len == 0) {
+ return 0;
+ }
+
+ if (tdb->read_only || tdb->traverse_read) {
+ tdb->ecode = TDB_ERR_RDONLY;
+ return -1;
+ }
+
+ if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0)
+ return -1;
+
+ if (tdb->map_ptr) {
+ memcpy(off + (char *)tdb->map_ptr, buf, len);
+ } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n",
+ off, len, strerror(errno)));
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ }
+ return 0;
+}
+
+/* Endian conversion: we only ever deal with 4 byte quantities */
+void *tdb_convert(void *buf, u32 size)
+{
+ u32 i, *p = (u32 *)buf;
+ for (i = 0; i < size / 4; i++)
+ p[i] = TDB_BYTEREV(p[i]);
+ return buf;
+}
+
+
+/* read a lump of data at a specified offset, maybe convert */
+static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
+ tdb_len_t len, int cv)
+{
+ if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
+ return -1;
+ }
+
+ if (tdb->map_ptr) {
+ memcpy(buf, off + (char *)tdb->map_ptr, len);
+ } else {
+ ssize_t ret = pread(tdb->fd, buf, len, off);
+ if (ret != (ssize_t)len) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d "
+ "len=%d ret=%d (%s) map_size=%d\n",
+ (int)off, (int)len, (int)ret, strerror(errno),
+ (int)tdb->map_size));
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+ }
+ }
+ if (cv) {
+ tdb_convert(buf, len);
+ }
+ return 0;
+}
+
+
+
+/*
+ do an unlocked scan of the hash table heads to find the next non-zero head. The value
+ will then be confirmed with the lock held
+*/
+static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
+{
+ u32 h = *chain;
+ if (tdb->map_ptr) {
+ for (;h < tdb->header.hash_size;h++) {
+ if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) {
+ break;
+ }
+ }
+ } else {
+ u32 off=0;
+ for (;h < tdb->header.hash_size;h++) {
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) {
+ break;
+ }
+ }
+ }
+ (*chain) = h;
+}
+
+
+int tdb_munmap(struct tdb_context *tdb)
+{
+ if (tdb->flags & TDB_INTERNAL)
+ return 0;
+
+#ifdef HAVE_MMAP
+ if (tdb->map_ptr) {
+ int ret = munmap(tdb->map_ptr, tdb->map_size);
+ if (ret != 0)
+ return ret;
+ }
+#endif
+ tdb->map_ptr = NULL;
+ return 0;
+}
+
+void tdb_mmap(struct tdb_context *tdb)
+{
+ if (tdb->flags & TDB_INTERNAL)
+ return;
+
+#ifdef HAVE_MMAP
+ if (!(tdb->flags & TDB_NOMMAP)) {
+ tdb->map_ptr = mmap(NULL, tdb->map_size,
+ PROT_READ|(tdb->read_only? 0:PROT_WRITE),
+ MAP_SHARED|MAP_FILE, tdb->fd, 0);
+
+ /*
+ * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
+ */
+
+ if (tdb->map_ptr == MAP_FAILED) {
+ tdb->map_ptr = NULL;
+ TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n",
+ tdb->map_size, strerror(errno)));
+ }
+ } else {
+ tdb->map_ptr = NULL;
+ }
+#else
+ tdb->map_ptr = NULL;
+#endif
+}
+
+/* expand a file. we prefer to use ftruncate, as that is what posix
+ says to use for mmap expansion */
+static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition)
+{
+ char buf[1024];
+
+ if (tdb->read_only || tdb->traverse_read) {
+ tdb->ecode = TDB_ERR_RDONLY;
+ return -1;
+ }
+
+ if (ftruncate(tdb->fd, size+addition) == -1) {
+ char b = 0;
+ if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
+ size+addition, strerror(errno)));
+ return -1;
+ }
+ }
+
+ /* now fill the file with something. This ensures that the
+ file isn't sparse, which would be very bad if we ran out of
+ disk. This must be done with write, not via mmap */
+ memset(buf, TDB_PAD_BYTE, sizeof(buf));
+ while (addition) {
+ int n = addition>sizeof(buf)?sizeof(buf):addition;
+ int ret = pwrite(tdb->fd, buf, n, size);
+ if (ret != n) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n",
+ n, strerror(errno)));
+ return -1;
+ }
+ addition -= n;
+ size += n;
+ }
+ return 0;
+}
+
+
+/* expand the database at least size bytes by expanding the underlying
+ file and doing the mmap again if necessary */
+int tdb_expand(struct tdb_context *tdb, tdb_off_t size)
+{
+ struct list_struct rec;
+ tdb_off_t offset;
+
+ if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n"));
+ return -1;
+ }
+
+ /* must know about any previous expansions by another process */
+ tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+
+ /* always make room for at least 10 more records, and round
+ the database up to a multiple of the page size */
+ size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size;
+
+ if (!(tdb->flags & TDB_INTERNAL))
+ tdb_munmap(tdb);
+
+ /*
+ * We must ensure the file is unmapped before doing this
+ * to ensure consistency with systems like OpenBSD where
+ * writes and mmaps are not consistent.
+ */
+
+ /* expand the file itself */
+ if (!(tdb->flags & TDB_INTERNAL)) {
+ if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
+ goto fail;
+ }
+
+ tdb->map_size += size;
+
+ if (tdb->flags & TDB_INTERNAL) {
+ char *new_map_ptr = (char *)realloc(tdb->map_ptr,
+ tdb->map_size);
+ if (!new_map_ptr) {
+ tdb->map_size -= size;
+ goto fail;
+ }
+ tdb->map_ptr = new_map_ptr;
+ } else {
+ /*
+ * We must ensure the file is remapped before adding the space
+ * to ensure consistency with systems like OpenBSD where
+ * writes and mmaps are not consistent.
+ */
+
+ /* We're ok if the mmap fails as we'll fallback to read/write */
+ tdb_mmap(tdb);
+ }
+
+ /* form a new freelist record */
+ memset(&rec,'\0',sizeof(rec));
+ rec.rec_len = size - sizeof(rec);
+
+ /* link it into the free list */
+ offset = tdb->map_size - size;
+ if (tdb_free(tdb, offset, &rec) == -1)
+ goto fail;
+
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return 0;
+ fail:
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return -1;
+}
+
+/* read/write a tdb_off_t */
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
+{
+ return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
+}
+
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
+{
+ tdb_off_t off = *d;
+ return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
+}
+
+
+/* read a lump of data, allocating the space for it */
+char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len)
+{
+ char *buf;
+
+ /* some systems don't like zero length malloc */
+ if (len == 0) {
+ len = 1;
+ }
+
+ if (!(buf = (char *)malloc(len))) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_OOM;
+ TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n",
+ len, strerror(errno)));
+ return TDB_ERRCODE(TDB_ERR_OOM, buf);
+ }
+ if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) {
+ SAFE_FREE(buf);
+ return NULL;
+ }
+ return buf;
+}
+
+/* Give a piece of tdb data to a parser */
+
+int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
+ tdb_off_t offset, tdb_len_t len,
+ int (*parser)(TDB_DATA key, TDB_DATA data,
+ void *private_data),
+ void *private_data)
+{
+ TDB_DATA data;
+ int result;
+
+ data.dsize = len;
+
+ if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) {
+ /*
+ * Optimize by avoiding the malloc/memcpy/free, point the
+ * parser directly at the mmap area.
+ */
+ if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) {
+ return -1;
+ }
+ data.dptr = offset + (char *)tdb->map_ptr;
+ return parser(key, data, private_data);
+ }
+
+ if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) {
+ return -1;
+ }
+
+ result = parser(key, data, private_data);
+ free(data.dptr);
+ return result;
+}
+
+/* read/write a record */
+int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+ if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
+ return -1;
+ if (TDB_BAD_MAGIC(rec)) {
+ /* Ensure ecode is set for log fn. */
+ tdb->ecode = TDB_ERR_CORRUPT;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
+ return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+ }
+ return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0);
+}
+
+int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+{
+ struct list_struct r = *rec;
+ return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r));
+}
+
+static const struct tdb_methods io_methods = {
+ tdb_read,
+ tdb_write,
+ tdb_next_hash_chain,
+ tdb_oob,
+ tdb_expand_file,
+ tdb_brlock
+};
+
+/*
+ initialise the default methods table
+*/
+void tdb_io_init(struct tdb_context *tdb)
+{
+ tdb->methods = &io_methods;
+}
diff --git a/source/tdb/common/lock.c b/source/tdb/common/lock.c
new file mode 100644
index 00000000000..8a964371d3a
--- /dev/null
+++ b/source/tdb/common/lock.c
@@ -0,0 +1,412 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/* a byte range locking function - return 0 on success
+ this functions locks/unlocks 1 byte at the specified offset.
+
+ On error, errno is also set so that errors are passed back properly
+ through tdb_open().
+
+ note that a len of zero means lock to end of file
+*/
+int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
+ int rw_type, int lck_type, int probe, size_t len)
+{
+ struct flock fl;
+ int ret;
+
+ if (tdb->flags & TDB_NOLOCK) {
+ return 0;
+ }
+
+ if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
+ tdb->ecode = TDB_ERR_RDONLY;
+ return -1;
+ }
+
+ fl.l_type = rw_type;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = offset;
+ fl.l_len = len;
+ fl.l_pid = 0;
+
+ do {
+ ret = fcntl(tdb->fd,lck_type,&fl);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret == -1) {
+ /* Generic lock error. errno set by fcntl.
+ * EAGAIN is an expected return from non-blocking
+ * locks. */
+ if (!probe && lck_type != F_SETLK) {
+ /* Ensure error code is set for log fun to examine. */
+ tdb->ecode = TDB_ERR_LOCK;
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
+ tdb->fd, offset, rw_type, lck_type, (int)len));
+ }
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+ return 0;
+}
+
+
+/*
+ upgrade a read lock to a write lock. This needs to be handled in a
+ special way as some OSes (such as solaris) have too conservative
+ deadlock detection and claim a deadlock when progress can be
+ made. For those OSes we may loop for a while.
+*/
+int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
+{
+ int count = 1000;
+ while (count--) {
+ struct timeval tv;
+ if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
+ return 0;
+ }
+ if (errno != EDEADLK) {
+ break;
+ }
+ /* sleep for as short a time as we can - more portable than usleep() */
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ select(0, NULL, NULL, NULL, &tv);
+ }
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
+ return -1;
+}
+
+
+/* lock a list in the database. list -1 is the alloc list */
+int tdb_lock(struct tdb_context *tdb, int list, int ltype)
+{
+ struct tdb_lock_type *new_lck;
+ int i;
+
+ /* a global lock allows us to avoid per chain locks */
+ if (tdb->global_lock.count &&
+ (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
+ return 0;
+ }
+
+ if (tdb->global_lock.count) {
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (list < -1 || list >= (int)tdb->header.hash_size) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
+ list, ltype));
+ return -1;
+ }
+ if (tdb->flags & TDB_NOLOCK)
+ return 0;
+
+ for (i=0; i<tdb->num_lockrecs; i++) {
+ if (tdb->lockrecs[i].list == list) {
+ if (tdb->lockrecs[i].count == 0) {
+ /*
+ * Can't happen, see tdb_unlock(). It should
+ * be an assert.
+ */
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: "
+ "lck->count == 0 for list %d", list));
+ }
+ /*
+ * Just increment the in-memory struct, posix locks
+ * don't stack.
+ */
+ tdb->lockrecs[i].count++;
+ return 0;
+ }
+ }
+
+ new_lck = (struct tdb_lock_type *)realloc(
+ tdb->lockrecs,
+ sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1));
+ if (new_lck == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ tdb->lockrecs = new_lck;
+
+ /* Since fcntl locks don't nest, we do a lock for the first one,
+ and simply bump the count for future ones */
+ if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW,
+ 0, 1)) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
+ "ltype=%d (%s)\n", list, ltype, strerror(errno)));
+ return -1;
+ }
+
+ tdb->num_locks++;
+
+ tdb->lockrecs[tdb->num_lockrecs].list = list;
+ tdb->lockrecs[tdb->num_lockrecs].count = 1;
+ tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
+ tdb->num_lockrecs += 1;
+
+ return 0;
+}
+
+/* unlock the database: returns void because it's too late for errors. */
+ /* changed to return int it may be interesting to know there
+ has been an error --simo */
+int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
+{
+ int ret = -1;
+ int i;
+ struct tdb_lock_type *lck = NULL;
+
+ /* a global lock allows us to avoid per chain locks */
+ if (tdb->global_lock.count &&
+ (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
+ return 0;
+ }
+
+ if (tdb->global_lock.count) {
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (tdb->flags & TDB_NOLOCK)
+ return 0;
+
+ /* Sanity checks */
+ if (list < -1 || list >= (int)tdb->header.hash_size) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
+ return ret;
+ }
+
+ for (i=0; i<tdb->num_lockrecs; i++) {
+ if (tdb->lockrecs[i].list == list) {
+ lck = &tdb->lockrecs[i];
+ break;
+ }
+ }
+
+ if ((lck == NULL) || (lck->count == 0)) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
+ return -1;
+ }
+
+ if (lck->count > 1) {
+ lck->count--;
+ return 0;
+ }
+
+ /*
+ * This lock has count==1 left, so we need to unlock it in the
+ * kernel. We don't bother with decrementing the in-memory array
+ * element, we're about to overwrite it with the last array element
+ * anyway.
+ */
+
+ ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
+ F_SETLKW, 0, 1);
+ tdb->num_locks--;
+
+ /*
+ * Shrink the array by overwriting the element just unlocked with the
+ * last array element.
+ */
+
+ if (tdb->num_lockrecs > 1) {
+ *lck = tdb->lockrecs[tdb->num_lockrecs-1];
+ }
+ tdb->num_lockrecs -= 1;
+
+ /*
+ * We don't bother with realloc when the array shrinks, but if we have
+ * a completely idle tdb we should get rid of the locked array.
+ */
+
+ if (tdb->num_lockrecs == 0) {
+ SAFE_FREE(tdb->lockrecs);
+ }
+
+ if (ret)
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n"));
+ return ret;
+}
+
+
+
+/* lock/unlock entire database */
+static int _tdb_lockall(struct tdb_context *tdb, int ltype)
+{
+ /* There are no locks on read-only dbs */
+ if (tdb->read_only || tdb->traverse_read)
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+
+ if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
+ tdb->global_lock.count++;
+ return 0;
+ }
+
+ if (tdb->global_lock.count) {
+ /* a global lock of a different type exists */
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (tdb->num_locks != 0) {
+ /* can't combine global and chain locks */
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, F_SETLKW,
+ 0, 4*tdb->header.hash_size)) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
+ return -1;
+ }
+
+ tdb->global_lock.count = 1;
+ tdb->global_lock.ltype = ltype;
+
+ return 0;
+}
+
+/* unlock entire db */
+static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
+{
+ /* There are no locks on read-only dbs */
+ if (tdb->read_only || tdb->traverse_read) {
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
+ return TDB_ERRCODE(TDB_ERR_LOCK, -1);
+ }
+
+ if (tdb->global_lock.count > 1) {
+ tdb->global_lock.count--;
+ return 0;
+ }
+
+ if (tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
+ 0, 4*tdb->header.hash_size)) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
+ return -1;
+ }
+
+ tdb->global_lock.count = 0;
+ tdb->global_lock.ltype = 0;
+
+ return 0;
+}
+
+/* lock entire database with write lock */
+int tdb_lockall(struct tdb_context *tdb)
+{
+ return _tdb_lockall(tdb, F_WRLCK);
+}
+
+/* unlock entire database with write lock */
+int tdb_unlockall(struct tdb_context *tdb)
+{
+ return _tdb_unlockall(tdb, F_WRLCK);
+}
+
+/* lock entire database with read lock */
+int tdb_lockall_read(struct tdb_context *tdb)
+{
+ return _tdb_lockall(tdb, F_RDLCK);
+}
+
+/* unlock entire database with read lock */
+int tdb_unlockall_read(struct tdb_context *tdb)
+{
+ return _tdb_unlockall(tdb, F_RDLCK);
+}
+
+/* lock/unlock one hash chain. This is meant to be used to reduce
+ contention - it cannot guarantee how many records will be locked */
+int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
+{
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+}
+
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
+{
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
+}
+
+int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
+{
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+}
+
+int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
+{
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
+}
+
+
+
+/* record lock stops delete underneath */
+int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+ return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;
+}
+
+/*
+ Write locks override our own fcntl readlocks, so check it here.
+ Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
+ an error to fail to get the lock here.
+*/
+int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+ struct tdb_traverse_lock *i;
+ for (i = &tdb->travlocks; i; i = i->next)
+ if (i->off == off)
+ return -1;
+ return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1);
+}
+
+/*
+ Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
+ an error to fail to get the lock here.
+*/
+int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+ return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1);
+}
+
+/* fcntl locks don't stack: avoid unlocking someone else's */
+int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off)
+{
+ struct tdb_traverse_lock *i;
+ u32 count = 0;
+
+ if (off == 0)
+ return 0;
+ for (i = &tdb->travlocks; i; i = i->next)
+ if (i->off == off)
+ count++;
+ return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
+}
diff --git a/source/tdb/common/open.c b/source/tdb/common/open.c
new file mode 100644
index 00000000000..3f0c35331b2
--- /dev/null
+++ b/source/tdb/common/open.c
@@ -0,0 +1,455 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
+static struct tdb_context *tdbs = NULL;
+
+
+/* This is based on the hash algorithm from gdbm */
+static unsigned int default_tdb_hash(TDB_DATA *key)
+{
+ u32 value; /* Used to compute the hash value. */
+ u32 i; /* Used to cycle through random values. */
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
+ value = (value + (key->dptr[i] << (i*5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
+
+/* initialise a new database with a specified hash size */
+static int tdb_new_database(struct tdb_context *tdb, int hash_size)
+{
+ struct tdb_header *newdb;
+ int size, ret = -1;
+
+ /* We make it up in memory, then write it out if not internal */
+ size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
+ if (!(newdb = (struct tdb_header *)calloc(size, 1)))
+ return TDB_ERRCODE(TDB_ERR_OOM, -1);
+
+ /* Fill in the header */
+ newdb->version = TDB_VERSION;
+ newdb->hash_size = hash_size;
+ if (tdb->flags & TDB_INTERNAL) {
+ tdb->map_size = size;
+ tdb->map_ptr = (char *)newdb;
+ memcpy(&tdb->header, newdb, sizeof(tdb->header));
+ /* Convert the `ondisk' version if asked. */
+ CONVERT(*newdb);
+ return 0;
+ }
+ if (lseek(tdb->fd, 0, SEEK_SET) == -1)
+ goto fail;
+
+ if (ftruncate(tdb->fd, 0) == -1)
+ goto fail;
+
+ /* This creates an endian-converted header, as if read from disk */
+ CONVERT(*newdb);
+ memcpy(&tdb->header, newdb, sizeof(tdb->header));
+ /* Don't endian-convert the magic food! */
+ memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
+ if (write(tdb->fd, newdb, size) != size) {
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+
+ fail:
+ SAFE_FREE(newdb);
+ return ret;
+}
+
+
+
+static int tdb_already_open(dev_t device,
+ ino_t ino)
+{
+ struct tdb_context *i;
+
+ for (i = tdbs; i; i = i->next) {
+ if (i->device == device && i->inode == ino) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* open the database, creating it if necessary
+
+ The open_flags and mode are passed straight to the open call on the
+ database file. A flags value of O_WRONLY is invalid. The hash size
+ is advisory, use zero for a default value.
+
+ Return is NULL on error, in which case errno is also set. Don't
+ try to call tdb_error or tdb_errname, just do strerror(errno).
+
+ @param name may be NULL for internal databases. */
+struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode)
+{
+ return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
+}
+
+/* a default logging function */
+static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
+static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
+{
+}
+
+
+struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode,
+ const struct tdb_logging_context *log_ctx,
+ tdb_hash_func hash_fn)
+{
+ struct tdb_context *tdb;
+ struct stat st;
+ int rev = 0, locked = 0;
+ unsigned char *vp;
+ u32 vertest;
+
+ if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
+ /* Can't log this */
+ errno = ENOMEM;
+ goto fail;
+ }
+ tdb_io_init(tdb);
+ tdb->fd = -1;
+ tdb->name = NULL;
+ tdb->map_ptr = NULL;
+ tdb->flags = tdb_flags;
+ tdb->open_flags = open_flags;
+ if (log_ctx) {
+ tdb->log = *log_ctx;
+ } else {
+ tdb->log.log_fn = null_log_fn;
+ tdb->log.log_private = NULL;
+ }
+ tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
+
+ /* cache the page size */
+ tdb->page_size = getpagesize();
+ if (tdb->page_size <= 0) {
+ tdb->page_size = 0x2000;
+ }
+
+ if ((open_flags & O_ACCMODE) == O_WRONLY) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
+ name));
+ errno = EINVAL;
+ goto fail;
+ }
+
+ if (hash_size == 0)
+ hash_size = DEFAULT_HASH_SIZE;
+ if ((open_flags & O_ACCMODE) == O_RDONLY) {
+ tdb->read_only = 1;
+ /* read only databases don't do locking or clear if first */
+ tdb->flags |= TDB_NOLOCK;
+ tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+ }
+
+ /* internal databases don't mmap or lock, and start off cleared */
+ if (tdb->flags & TDB_INTERNAL) {
+ tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
+ tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+ if (tdb_new_database(tdb, hash_size) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!"));
+ goto fail;
+ }
+ goto internal;
+ }
+
+ if ((tdb->fd = open(name, open_flags, mode)) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
+ name, strerror(errno)));
+ goto fail; /* errno set by open(2) */
+ }
+
+ /* ensure there is only one process initialising at once */
+ if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
+ name, strerror(errno)));
+ goto fail; /* errno set by tdb_brlock */
+ }
+
+ /* we need to zero database if we are the only one with it open */
+ if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
+ (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
+ open_flags |= O_CREAT;
+ if (ftruncate(tdb->fd, 0) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
+ "failed to truncate %s: %s\n",
+ name, strerror(errno)));
+ goto fail; /* errno set by ftruncate */
+ }
+ }
+
+ if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
+ || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
+ || (tdb->header.version != TDB_VERSION
+ && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
+ /* its not a valid database - possibly initialise it */
+ if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
+ errno = EIO; /* ie bad format or something */
+ goto fail;
+ }
+ rev = (tdb->flags & TDB_CONVERT);
+ }
+ vp = (unsigned char *)&tdb->header.version;
+ vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
+ (((u32)vp[2]) << 8) | (u32)vp[3];
+ tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
+ if (!rev)
+ tdb->flags &= ~TDB_CONVERT;
+ else {
+ tdb->flags |= TDB_CONVERT;
+ tdb_convert(&tdb->header, sizeof(tdb->header));
+ }
+ if (fstat(tdb->fd, &st) == -1)
+ goto fail;
+
+ if (tdb->header.rwlocks != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
+ goto fail;
+ }
+
+ /* Is it already in the open list? If so, fail. */
+ if (tdb_already_open(st.st_dev, st.st_ino)) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
+ "%s (%d,%d) is already open in this process\n",
+ name, (int)st.st_dev, (int)st.st_ino));
+ errno = EBUSY;
+ goto fail;
+ }
+
+ if (!(tdb->name = (char *)strdup(name))) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
+ tdb->map_size = st.st_size;
+ tdb->device = st.st_dev;
+ tdb->inode = st.st_ino;
+ tdb_mmap(tdb);
+ if (locked) {
+ if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
+ "failed to take ACTIVE_LOCK on %s: %s\n",
+ name, strerror(errno)));
+ goto fail;
+ }
+
+ }
+
+ /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
+ we didn't get the initial exclusive lock as we need to let all other
+ users know we're using it. */
+
+ if (tdb_flags & TDB_CLEAR_IF_FIRST) {
+ /* leave this lock in place to indicate it's in use */
+ if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
+ goto fail;
+ }
+
+ /* if needed, run recovery */
+ if (tdb_transaction_recover(tdb) == -1) {
+ goto fail;
+ }
+
+ internal:
+ /* Internal (memory-only) databases skip all the code above to
+ * do with disk files, and resume here by releasing their
+ * global lock and hooking into the active list. */
+ if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
+ goto fail;
+ tdb->next = tdbs;
+ tdbs = tdb;
+ return tdb;
+
+ fail:
+ { int save_errno = errno;
+
+ if (!tdb)
+ return NULL;
+
+ if (tdb->map_ptr) {
+ if (tdb->flags & TDB_INTERNAL)
+ SAFE_FREE(tdb->map_ptr);
+ else
+ tdb_munmap(tdb);
+ }
+ SAFE_FREE(tdb->name);
+ if (tdb->fd != -1)
+ if (close(tdb->fd) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
+ SAFE_FREE(tdb);
+ errno = save_errno;
+ return NULL;
+ }
+}
+
+/**
+ * Close a database.
+ *
+ * @returns -1 for error; 0 for success.
+ **/
+int tdb_close(struct tdb_context *tdb)
+{
+ struct tdb_context **i;
+ int ret = 0;
+
+ if (tdb->transaction) {
+ tdb_transaction_cancel(tdb);
+ }
+
+ if (tdb->map_ptr) {
+ if (tdb->flags & TDB_INTERNAL)
+ SAFE_FREE(tdb->map_ptr);
+ else
+ tdb_munmap(tdb);
+ }
+ SAFE_FREE(tdb->name);
+ if (tdb->fd != -1)
+ ret = close(tdb->fd);
+ SAFE_FREE(tdb->lockrecs);
+
+ /* Remove from contexts list */
+ for (i = &tdbs; *i; i = &(*i)->next) {
+ if (*i == tdb) {
+ *i = tdb->next;
+ break;
+ }
+ }
+
+ memset(tdb, 0, sizeof(*tdb));
+ SAFE_FREE(tdb);
+
+ return ret;
+}
+
+/* register a loging function */
+void tdb_set_logging_function(struct tdb_context *tdb,
+ const struct tdb_logging_context *log_ctx)
+{
+ tdb->log = *log_ctx;
+}
+
+void *tdb_get_logging_private(struct tdb_context *tdb)
+{
+ return tdb->log.log_private;
+}
+
+/* reopen a tdb - this can be used after a fork to ensure that we have an independent
+ seek pointer from our parent and to re-establish locks */
+int tdb_reopen(struct tdb_context *tdb)
+{
+ struct stat st;
+
+ if (tdb->flags & TDB_INTERNAL) {
+ return 0; /* Nothing to do. */
+ }
+
+ if (tdb->num_locks != 0 || tdb->global_lock.count) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
+ goto fail;
+ }
+
+ if (tdb->transaction != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
+ goto fail;
+ }
+
+ if (tdb_munmap(tdb) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
+ goto fail;
+ }
+ if (close(tdb->fd) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
+ tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
+ if (tdb->fd == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
+ goto fail;
+ }
+ if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
+ (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
+ goto fail;
+ }
+ if (fstat(tdb->fd, &st) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
+ goto fail;
+ }
+ if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
+ goto fail;
+ }
+ tdb_mmap(tdb);
+
+ return 0;
+
+fail:
+ tdb_close(tdb);
+ return -1;
+}
+
+/* reopen all tdb's */
+int tdb_reopen_all(int parent_longlived)
+{
+ struct tdb_context *tdb;
+
+ for (tdb=tdbs; tdb; tdb = tdb->next) {
+ /*
+ * If the parent is longlived (ie. a
+ * parent daemon architecture), we know
+ * it will keep it's active lock on a
+ * tdb opened with CLEAR_IF_FIRST. Thus
+ * for child processes we don't have to
+ * add an active lock. This is essential
+ * to improve performance on systems that
+ * keep POSIX locks as a non-scalable data
+ * structure in the kernel.
+ */
+ if (parent_longlived) {
+ /* Ensure no clear-if-first. */
+ tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+ }
+
+ if (tdb_reopen(tdb) != 0)
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/source/tdb/common/tdb.c b/source/tdb/common/tdb.c
new file mode 100644
index 00000000000..bf4c01d1b3a
--- /dev/null
+++ b/source/tdb/common/tdb.c
@@ -0,0 +1,482 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+TDB_DATA tdb_null;
+
+/*
+ increment the tdb sequence number if the tdb has been opened using
+ the TDB_SEQNUM flag
+*/
+static void tdb_increment_seqnum(struct tdb_context *tdb)
+{
+ tdb_off_t seqnum=0;
+
+ if (!(tdb->flags & TDB_SEQNUM)) {
+ return;
+ }
+
+ if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
+ return;
+ }
+
+ /* we ignore errors from this, as we have no sane way of
+ dealing with them.
+ */
+ tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+ seqnum++;
+ tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
+
+ tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
+}
+
+static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ return memcmp(data.dptr, key.dptr, data.dsize);
+}
+
+/* Returns 0 on fail. On success, return offset of record, and fills
+ in rec */
+static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
+ struct list_struct *r)
+{
+ tdb_off_t rec_ptr;
+
+ /* read in the hash top */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+ return 0;
+
+ /* keep looking until we find the right record */
+ while (rec_ptr) {
+ if (tdb_rec_read(tdb, rec_ptr, r) == -1)
+ return 0;
+
+ if (!TDB_DEAD(r) && hash==r->full_hash
+ && key.dsize==r->key_len
+ && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r),
+ r->key_len, tdb_key_compare,
+ NULL) == 0) {
+ return rec_ptr;
+ }
+ rec_ptr = r->next;
+ }
+ return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
+}
+
+/* As tdb_find, but if you succeed, keep the lock */
+tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
+ struct list_struct *rec)
+{
+ u32 rec_ptr;
+
+ if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
+ return 0;
+ if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
+ tdb_unlock(tdb, BUCKET(hash), locktype);
+ return rec_ptr;
+}
+
+
+/* update an entry in place - this only works if the new data size
+ is <= the old data size and the key exists.
+ on failure return -1.
+*/
+static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
+{
+ struct list_struct rec;
+ tdb_off_t rec_ptr;
+
+ /* find entry */
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
+ return -1;
+
+ /* must be long enough key, data and tailer */
+ if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) {
+ tdb->ecode = TDB_SUCCESS; /* Not really an error */
+ return -1;
+ }
+
+ if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
+ dbuf.dptr, dbuf.dsize) == -1)
+ return -1;
+
+ if (dbuf.dsize != rec.data_len) {
+ /* update size */
+ rec.data_len = dbuf.dsize;
+ return tdb_rec_write(tdb, rec_ptr, &rec);
+ }
+
+ return 0;
+}
+
+/* find an entry in the database given a key */
+/* If an entry doesn't exist tdb_err will be set to
+ * TDB_ERR_NOEXIST. If a key has no data attached
+ * then the TDB_DATA will have zero length but
+ * a non-zero pointer
+ */
+TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
+{
+ tdb_off_t rec_ptr;
+ struct list_struct rec;
+ TDB_DATA ret;
+ u32 hash;
+
+ /* find which hash bucket it is in */
+ hash = tdb->hash_fn(&key);
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
+ return tdb_null;
+
+ ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
+ rec.data_len);
+ ret.dsize = rec.data_len;
+ tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
+ return ret;
+}
+
+/*
+ * Find an entry in the database and hand the record's data to a parsing
+ * function. The parsing function is executed under the chain read lock, so it
+ * should be fast and should not block on other syscalls.
+ *
+ * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
+ *
+ * For mmapped tdb's that do not have a transaction open it points the parsing
+ * function directly at the mmap area, it avoids the malloc/memcpy in this
+ * case. If a transaction is open or no mmap is available, it has to do
+ * malloc/read/parse/free.
+ *
+ * This is interesting for all readers of potentially large data structures in
+ * the tdb records, ldb indexes being one example.
+ */
+
+int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
+ int (*parser)(TDB_DATA key, TDB_DATA data,
+ void *private_data),
+ void *private_data)
+{
+ tdb_off_t rec_ptr;
+ struct list_struct rec;
+ int ret;
+ u32 hash;
+
+ /* find which hash bucket it is in */
+ hash = tdb->hash_fn(&key);
+
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
+ return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
+ }
+
+ ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len,
+ rec.data_len, parser, private_data);
+
+ tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
+
+ return ret;
+}
+
+/* check if an entry in the database exists
+
+ note that 1 is returned if the key is found and 0 is returned if not found
+ this doesn't match the conventions in the rest of this module, but is
+ compatible with gdbm
+*/
+static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
+{
+ struct list_struct rec;
+
+ if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
+ return 0;
+ tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
+ return 1;
+}
+
+int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
+{
+ u32 hash = tdb->hash_fn(&key);
+ return tdb_exists_hash(tdb, key, hash);
+}
+
+/* actually delete an entry in the database given the offset */
+int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec)
+{
+ tdb_off_t last_ptr, i;
+ struct list_struct lastrec;
+
+ if (tdb->read_only || tdb->traverse_read) return -1;
+
+ if (tdb_write_lock_record(tdb, rec_ptr) == -1) {
+ /* Someone traversing here: mark it as dead */
+ rec->magic = TDB_DEAD_MAGIC;
+ return tdb_rec_write(tdb, rec_ptr, rec);
+ }
+ if (tdb_write_unlock_record(tdb, rec_ptr) != 0)
+ return -1;
+
+ /* find previous record in hash chain */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
+ return -1;
+ for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next)
+ if (tdb_rec_read(tdb, i, &lastrec) == -1)
+ return -1;
+
+ /* unlink it: next ptr is at start of record. */
+ if (last_ptr == 0)
+ last_ptr = TDB_HASH_TOP(rec->full_hash);
+ if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1)
+ return -1;
+
+ /* recover the space */
+ if (tdb_free(tdb, rec_ptr, rec) == -1)
+ return -1;
+ return 0;
+}
+
+/* delete an entry in the database given a key */
+static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
+{
+ tdb_off_t rec_ptr;
+ struct list_struct rec;
+ int ret;
+
+ if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
+ return -1;
+ ret = tdb_do_delete(tdb, rec_ptr, &rec);
+
+ if (ret == 0) {
+ tdb_increment_seqnum(tdb);
+ }
+
+ if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n"));
+ return ret;
+}
+
+int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
+{
+ u32 hash = tdb->hash_fn(&key);
+ return tdb_delete_hash(tdb, key, hash);
+}
+
+/* store an element in the database, replacing any existing element
+ with the same key
+
+ return 0 on success, -1 on failure
+*/
+int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
+{
+ struct list_struct rec;
+ u32 hash;
+ tdb_off_t rec_ptr;
+ char *p = NULL;
+ int ret = -1;
+
+ if (tdb->read_only || tdb->traverse_read) {
+ tdb->ecode = TDB_ERR_RDONLY;
+ return -1;
+ }
+
+ /* find which hash bucket it is in */
+ hash = tdb->hash_fn(&key);
+ if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+ return -1;
+
+ /* check for it existing, on insert. */
+ if (flag == TDB_INSERT) {
+ if (tdb_exists_hash(tdb, key, hash)) {
+ tdb->ecode = TDB_ERR_EXISTS;
+ goto fail;
+ }
+ } else {
+ /* first try in-place update, on modify or replace. */
+ if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
+ ret = 0;
+ goto fail; /* Well, not really failed */
+ }
+ if (tdb->ecode == TDB_ERR_NOEXIST &&
+ flag == TDB_MODIFY) {
+ /* if the record doesn't exist and we are in TDB_MODIFY mode then
+ we should fail the store */
+ goto fail;
+ }
+ }
+ /* reset the error code potentially set by the tdb_update() */
+ tdb->ecode = TDB_SUCCESS;
+
+ /* delete any existing record - if it doesn't exist we don't
+ care. Doing this first reduces fragmentation, and avoids
+ coalescing with `allocated' block before it's updated. */
+ if (flag != TDB_INSERT)
+ tdb_delete_hash(tdb, key, hash);
+
+ /* Copy key+value *before* allocating free space in case malloc
+ fails and we are left with a dead spot in the tdb. */
+
+ if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
+ tdb->ecode = TDB_ERR_OOM;
+ goto fail;
+ }
+
+ memcpy(p, key.dptr, key.dsize);
+ if (dbuf.dsize)
+ memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
+
+ /* we have to allocate some space */
+ if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
+ goto fail;
+
+ /* Read hash top into next ptr */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
+ goto fail;
+
+ rec.key_len = key.dsize;
+ rec.data_len = dbuf.dsize;
+ rec.full_hash = hash;
+ rec.magic = TDB_MAGIC;
+
+ /* write out and point the top of the hash chain at it */
+ if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
+ || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
+ || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
+ /* Need to tdb_unallocate() here */
+ goto fail;
+ }
+
+ ret = 0;
+ fail:
+ if (ret == 0) {
+ tdb_increment_seqnum(tdb);
+ }
+
+ SAFE_FREE(p);
+ tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+ return ret;
+}
+
+
+/* Append to an entry. Create if not exist. */
+int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+{
+ u32 hash;
+ TDB_DATA dbuf;
+ int ret = -1;
+
+ /* find which hash bucket it is in */
+ hash = tdb->hash_fn(&key);
+ if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+ return -1;
+
+ dbuf = tdb_fetch(tdb, key);
+
+ if (dbuf.dptr == NULL) {
+ dbuf.dptr = (char *)malloc(new_dbuf.dsize);
+ } else {
+ dbuf.dptr = (char *)realloc(dbuf.dptr,
+ dbuf.dsize + new_dbuf.dsize);
+ }
+
+ if (dbuf.dptr == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ goto failed;
+ }
+
+ memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
+ dbuf.dsize += new_dbuf.dsize;
+
+ ret = tdb_store(tdb, key, dbuf, 0);
+
+failed:
+ tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+ SAFE_FREE(dbuf.dptr);
+ return ret;
+}
+
+
+/*
+ return the name of the current tdb file
+ useful for external logging functions
+*/
+const char *tdb_name(struct tdb_context *tdb)
+{
+ return tdb->name;
+}
+
+/*
+ return the underlying file descriptor being used by tdb, or -1
+ useful for external routines that want to check the device/inode
+ of the fd
+*/
+int tdb_fd(struct tdb_context *tdb)
+{
+ return tdb->fd;
+}
+
+/*
+ return the current logging function
+ useful for external tdb routines that wish to log tdb errors
+*/
+tdb_log_func tdb_log_fn(struct tdb_context *tdb)
+{
+ return tdb->log.log_fn;
+}
+
+
+/*
+ get the tdb sequence number. Only makes sense if the writers opened
+ with TDB_SEQNUM set. Note that this sequence number will wrap quite
+ quickly, so it should only be used for a 'has something changed'
+ test, not for code that relies on the count of the number of changes
+ made. If you want a counter then use a tdb record.
+
+ The aim of this sequence number is to allow for a very lightweight
+ test of a possible tdb change.
+*/
+int tdb_get_seqnum(struct tdb_context *tdb)
+{
+ tdb_off_t seqnum=0;
+
+ tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+ return seqnum;
+}
+
+int tdb_hash_size(struct tdb_context *tdb)
+{
+ return tdb->header.hash_size;
+}
+
+size_t tdb_map_size(struct tdb_context *tdb)
+{
+ return tdb->map_size;
+}
+
+int tdb_get_flags(struct tdb_context *tdb)
+{
+ return tdb->flags;
+}
+
diff --git a/source/tdb/common/tdb_private.h b/source/tdb/common/tdb_private.h
new file mode 100644
index 00000000000..7fc136c6a70
--- /dev/null
+++ b/source/tdb/common/tdb_private.h
@@ -0,0 +1,211 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library - private includes
+
+ Copyright (C) Andrew Tridgell 2005
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/time.h"
+#include "system/shmem.h"
+#include "system/select.h"
+#include "tdb.h"
+
+#ifndef u32
+#define u32 unsigned
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+#define getpagesize() 0x2000
+#endif
+
+typedef u32 tdb_len_t;
+typedef u32 tdb_off_t;
+
+#ifndef offsetof
+#define offsetof(t,f) ((unsigned int)&((t *)0)->f)
+#endif
+
+#define TDB_MAGIC_FOOD "TDB file\n"
+#define TDB_VERSION (0x26011967 + 6)
+#define TDB_MAGIC (0x26011999U)
+#define TDB_FREE_MAGIC (~TDB_MAGIC)
+#define TDB_DEAD_MAGIC (0xFEE1DEAD)
+#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
+#define TDB_ALIGNMENT 4
+#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
+#define DEFAULT_HASH_SIZE 131
+#define FREELIST_TOP (sizeof(struct tdb_header))
+#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
+#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
+#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
+#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
+#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t))
+#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))
+#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1)
+#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start)
+#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number)
+#define TDB_PAD_BYTE 0x42
+#define TDB_PAD_U32 0x42424242
+
+/* NB assumes there is a local variable called "tdb" that is the
+ * current context, also takes doubly-parenthesized print-style
+ * argument. */
+#define TDB_LOG(x) tdb->log.log_fn x
+
+/* lock offsets */
+#define GLOBAL_LOCK 0
+#define ACTIVE_LOCK 4
+#define TRANSACTION_LOCK 8
+
+/* 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)
+#endif
+
+#define BUCKET(hash) ((hash) % tdb->header.hash_size)
+
+#define DOCONV() (tdb->flags & TDB_CONVERT)
+#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x)
+
+
+/* the body of the database is made of one list_struct for the free space
+ plus a separate data list for each hash value */
+struct list_struct {
+ tdb_off_t next; /* offset of the next record in the list */
+ tdb_len_t rec_len; /* total byte length of record */
+ tdb_len_t key_len; /* byte length of key */
+ tdb_len_t data_len; /* byte length of data */
+ u32 full_hash; /* the full 32 bit hash of the key */
+ u32 magic; /* try to catch errors */
+ /* the following union is implied:
+ union {
+ char record[rec_len];
+ struct {
+ char key[key_len];
+ char data[data_len];
+ }
+ u32 totalsize; (tailer)
+ }
+ */
+};
+
+
+/* this is stored at the front of every database */
+struct tdb_header {
+ char magic_food[32]; /* for /etc/magic */
+ u32 version; /* version of the code */
+ u32 hash_size; /* number of hash entries */
+ tdb_off_t rwlocks; /* obsolete - kept to detect old formats */
+ tdb_off_t recovery_start; /* offset of transaction recovery region */
+ tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
+ tdb_off_t reserved[29];
+};
+
+struct tdb_lock_type {
+ int list;
+ u32 count;
+ u32 ltype;
+};
+
+struct tdb_traverse_lock {
+ struct tdb_traverse_lock *next;
+ u32 off;
+ u32 hash;
+ int lock_rw;
+};
+
+
+struct tdb_methods {
+ int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int );
+ int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
+ void (*next_hash_chain)(struct tdb_context *, u32 *);
+ int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
+ int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
+ int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t);
+};
+
+struct tdb_context {
+ char *name; /* the name of the database */
+ void *map_ptr; /* where it is currently mapped */
+ int fd; /* open file descriptor for the database */
+ tdb_len_t map_size; /* how much space has been mapped */
+ int read_only; /* opened read-only */
+ int traverse_read; /* read-only traversal */
+ struct tdb_lock_type global_lock;
+ int num_lockrecs;
+ struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
+ enum TDB_ERROR ecode; /* error code for last tdb error */
+ struct tdb_header header; /* a cached copy of the header */
+ u32 flags; /* the flags passed to tdb_open */
+ struct tdb_traverse_lock travlocks; /* current traversal locks */
+ struct tdb_context *next; /* all tdbs to avoid multiple opens */
+ dev_t device; /* uniquely identifies this tdb */
+ ino_t inode; /* uniquely identifies this tdb */
+ struct tdb_logging_context log;
+ unsigned int (*hash_fn)(TDB_DATA *key);
+ int open_flags; /* flags used in the open - needed by reopen */
+ unsigned int num_locks; /* number of chain locks held */
+ const struct tdb_methods *methods;
+ struct tdb_transaction *transaction;
+ int page_size;
+};
+
+
+/*
+ internal prototypes
+*/
+int tdb_munmap(struct tdb_context *tdb);
+void tdb_mmap(struct tdb_context *tdb);
+int tdb_lock(struct tdb_context *tdb, int list, int ltype);
+int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
+int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
+int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
+int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+void *tdb_convert(void *buf, u32 size);
+int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
+int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
+int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
+int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
+int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
+char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
+int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
+ tdb_off_t offset, tdb_len_t len,
+ int (*parser)(TDB_DATA key, TDB_DATA data,
+ void *private_data),
+ void *private_data);
+tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
+ struct list_struct *rec);
+void tdb_io_init(struct tdb_context *tdb);
+int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
+int rec_free_read(struct tdb_context *tdb, tdb_off_t off,
+ struct list_struct *rec);
+
+
diff --git a/source/tdb/tdbback.c b/source/tdb/common/tdbback.c
index 7967a6bbf54..28de85c29f8 100644
--- a/source/tdb/tdbback.c
+++ b/source/tdb/common/tdbback.c
@@ -63,7 +63,7 @@ char *add_suffix(const char *name, const char *suffix)
{
char *ret;
int len = strlen(name) + strlen(suffix) + 1;
- ret = malloc(len);
+ ret = (char *)malloc(len);
if (!ret) {
fprintf(stderr,"Out of memory!\n");
exit(1);
@@ -77,7 +77,7 @@ static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state;
if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) {
- fprintf(stderr,"Failed to insert into %s\n", tdb_new->name);
+ fprintf(stderr,"Failed to insert into %s\n", tdb_name(tdb));
failed = 1;
return 1;
}
@@ -95,7 +95,7 @@ static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
only doing the backup if its OK
this function is also used for restore
*/
-int backup_tdb(const char *old_name, const char *new_name)
+int backup_tdb(const char *old_name, const char *new_name, int hash_size)
{
TDB_CONTEXT *tdb;
TDB_CONTEXT *tdb_new;
@@ -122,7 +122,8 @@ int backup_tdb(const char *old_name, const char *new_name)
/* create the new tdb */
unlink(tmp_name);
- tdb_new = tdb_open(tmp_name, tdb->header.hash_size,
+ tdb_new = tdb_open(tmp_name,
+ hash_size ? hash_size : tdb_hash_size(tdb),
TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL,
st.st_mode & 0777);
if (!tdb_new) {
@@ -179,7 +180,7 @@ int backup_tdb(const char *old_name, const char *new_name)
}
/* make sure the new tdb has reached stable storage */
- fsync(tdb_new->fd);
+ fsync(tdb_fd(tdb_new));
/* close the new tdb and rename it to .bak */
tdb_close(tdb_new);
@@ -217,7 +218,7 @@ int verify_tdb(const char *fname, const char *bak_name)
/* count is < 0 means an error */
if (count < 0) {
printf("restoring %s\n", fname);
- return backup_tdb(bak_name, fname);
+ return backup_tdb(bak_name, fname, 0);
}
printf("%s : %d records\n", fname, count);
diff --git a/source/tdb/common/transaction.c b/source/tdb/common/transaction.c
new file mode 100644
index 00000000000..24aa5c32234
--- /dev/null
+++ b/source/tdb/common/transaction.c
@@ -0,0 +1,1054 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 2005
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/*
+ transaction design:
+
+ - only allow a single transaction at a time per database. This makes
+ using the transaction API simpler, as otherwise the caller would
+ have to cope with temporary failures in transactions that conflict
+ with other current transactions
+
+ - keep the transaction recovery information in the same file as the
+ database, using a special 'transaction recovery' record pointed at
+ by the header. This removes the need for extra journal files as
+ used by some other databases
+
+ - dynamically allocated the transaction recover record, re-using it
+ for subsequent transactions. If a larger record is needed then
+ tdb_free() the old record to place it on the normal tdb freelist
+ before allocating the new record
+
+ - during transactions, keep a linked list of writes all that have
+ been performed by intercepting all tdb_write() calls. The hooked
+ transaction versions of tdb_read() and tdb_write() check this
+ linked list and try to use the elements of the list in preference
+ to the real database.
+
+ - don't allow any locks to be held when a transaction starts,
+ otherwise we can end up with deadlock (plus lack of lock nesting
+ in posix locks would mean the lock is lost)
+
+ - if the caller gains a lock during the transaction but doesn't
+ release it then fail the commit
+
+ - allow for nested calls to tdb_transaction_start(), re-using the
+ existing transaction record. If the inner transaction is cancelled
+ then a subsequent commit will fail
+
+ - keep a mirrored copy of the tdb hash chain heads to allow for the
+ fast hash heads scan on traverse, updating the mirrored copy in
+ the transaction version of tdb_write
+
+ - allow callers to mix transaction and non-transaction use of tdb,
+ although once a transaction is started then an exclusive lock is
+ gained until the transaction is committed or cancelled
+
+ - the commit stategy involves first saving away all modified data
+ into a linearised buffer in the transaction recovery area, then
+ marking the transaction recovery area with a magic value to
+ indicate a valid recovery record. In total 4 fsync/msync calls are
+ needed per commit to prevent race conditions. It might be possible
+ to reduce this to 3 or even 2 with some more work.
+
+ - check for a valid recovery record on open of the tdb, while the
+ global lock is held. Automatically recover from the transaction
+ recovery area if needed, then continue with the open as
+ usual. This allows for smooth crash recovery with no administrator
+ intervention.
+
+ - if TDB_NOSYNC is passed to flags in tdb_open then transactions are
+ still available, but no transaction recovery area is used and no
+ fsync/msync calls are made.
+
+*/
+
+int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
+ int rw_type, int lck_type, int probe, size_t len);
+
+struct tdb_transaction_el {
+ struct tdb_transaction_el *next, *prev;
+ tdb_off_t offset;
+ tdb_len_t length;
+ unsigned char *data;
+};
+
+/*
+ hold the context of any current transaction
+*/
+struct tdb_transaction {
+ /* we keep a mirrored copy of the tdb hash heads here so
+ tdb_next_hash_chain() can operate efficiently */
+ u32 *hash_heads;
+
+ /* the original io methods - used to do IOs to the real db */
+ const struct tdb_methods *io_methods;
+
+ /* the list of transaction elements. We use a doubly linked
+ list with a last pointer to allow us to keep the list
+ ordered, with first element at the front of the list. It
+ needs to be doubly linked as the read/write traversals need
+ to be backwards, while the commit needs to be forwards */
+ struct tdb_transaction_el *elements, *elements_last;
+
+ /* non-zero when an internal transaction error has
+ occurred. All write operations will then fail until the
+ transaction is ended */
+ int transaction_error;
+
+ /* when inside a transaction we need to keep track of any
+ nested tdb_transaction_start() calls, as these are allowed,
+ but don't create a new transaction */
+ int nesting;
+
+ /* old file size before transaction */
+ tdb_len_t old_map_size;
+};
+
+
+/*
+ read while in a transaction. We need to check first if the data is in our list
+ of transaction elements, then if not do a real read
+*/
+static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
+ tdb_len_t len, int cv)
+{
+ struct tdb_transaction_el *el;
+
+ /* we need to walk the list backwards to get the most recent data */
+ for (el=tdb->transaction->elements_last;el;el=el->prev) {
+ tdb_len_t partial;
+
+ if (off+len <= el->offset) {
+ continue;
+ }
+ if (off >= el->offset + el->length) {
+ continue;
+ }
+
+ /* an overlapping read - needs to be split into up to
+ 2 reads and a memcpy */
+ if (off < el->offset) {
+ partial = el->offset - off;
+ if (transaction_read(tdb, off, buf, partial, cv) != 0) {
+ goto fail;
+ }
+ len -= partial;
+ off += partial;
+ buf = (void *)(partial + (char *)buf);
+ }
+ if (off + len <= el->offset + el->length) {
+ partial = len;
+ } else {
+ partial = el->offset + el->length - off;
+ }
+ memcpy(buf, el->data + (off - el->offset), partial);
+ if (cv) {
+ tdb_convert(buf, len);
+ }
+ len -= partial;
+ off += partial;
+ buf = (void *)(partial + (char *)buf);
+
+ if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
+ goto fail;
+ }
+
+ return 0;
+ }
+
+ /* its not in the transaction elements - do a real read */
+ return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv);
+
+fail:
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len));
+ tdb->ecode = TDB_ERR_IO;
+ tdb->transaction->transaction_error = 1;
+ return -1;
+}
+
+
+/*
+ write while in a transaction
+*/
+static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
+ const void *buf, tdb_len_t len)
+{
+ struct tdb_transaction_el *el, *best_el=NULL;
+
+ if (len == 0) {
+ return 0;
+ }
+
+ /* if the write is to a hash head, then update the transaction
+ hash heads */
+ if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP &&
+ off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) {
+ u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t);
+ memcpy(&tdb->transaction->hash_heads[chain], buf, len);
+ }
+
+ /* first see if we can replace an existing entry */
+ for (el=tdb->transaction->elements_last;el;el=el->prev) {
+ tdb_len_t partial;
+
+ if (best_el == NULL && off == el->offset+el->length) {
+ best_el = el;
+ }
+
+ if (off+len <= el->offset) {
+ continue;
+ }
+ if (off >= el->offset + el->length) {
+ continue;
+ }
+
+ /* an overlapping write - needs to be split into up to
+ 2 writes and a memcpy */
+ if (off < el->offset) {
+ partial = el->offset - off;
+ if (transaction_write(tdb, off, buf, partial) != 0) {
+ goto fail;
+ }
+ len -= partial;
+ off += partial;
+ buf = (const void *)(partial + (const char *)buf);
+ }
+ if (off + len <= el->offset + el->length) {
+ partial = len;
+ } else {
+ partial = el->offset + el->length - off;
+ }
+ memcpy(el->data + (off - el->offset), buf, partial);
+ len -= partial;
+ off += partial;
+ buf = (const void *)(partial + (const char *)buf);
+
+ if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
+ goto fail;
+ }
+
+ return 0;
+ }
+
+ /* see if we can append the new entry to an existing entry */
+ if (best_el && best_el->offset + best_el->length == off &&
+ (off+len < tdb->transaction->old_map_size ||
+ off > tdb->transaction->old_map_size)) {
+ unsigned char *data = best_el->data;
+ el = best_el;
+ el->data = (unsigned char *)realloc(el->data,
+ el->length + len);
+ if (el->data == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ tdb->transaction->transaction_error = 1;
+ el->data = data;
+ return -1;
+ }
+ if (buf) {
+ memcpy(el->data + el->length, buf, len);
+ } else {
+ memset(el->data + el->length, TDB_PAD_BYTE, len);
+ }
+ el->length += len;
+ return 0;
+ }
+
+ /* add a new entry at the end of the list */
+ el = (struct tdb_transaction_el *)malloc(sizeof(*el));
+ if (el == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ tdb->transaction->transaction_error = 1;
+ return -1;
+ }
+ el->next = NULL;
+ el->prev = tdb->transaction->elements_last;
+ el->offset = off;
+ el->length = len;
+ el->data = (unsigned char *)malloc(len);
+ if (el->data == NULL) {
+ free(el);
+ tdb->ecode = TDB_ERR_OOM;
+ tdb->transaction->transaction_error = 1;
+ return -1;
+ }
+ if (buf) {
+ memcpy(el->data, buf, len);
+ } else {
+ memset(el->data, TDB_PAD_BYTE, len);
+ }
+ if (el->prev) {
+ el->prev->next = el;
+ } else {
+ tdb->transaction->elements = el;
+ }
+ tdb->transaction->elements_last = el;
+ return 0;
+
+fail:
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len));
+ tdb->ecode = TDB_ERR_IO;
+ tdb->transaction->transaction_error = 1;
+ return -1;
+}
+
+/*
+ accelerated hash chain head search, using the cached hash heads
+*/
+static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain)
+{
+ u32 h = *chain;
+ for (;h < tdb->header.hash_size;h++) {
+ /* the +1 takes account of the freelist */
+ if (0 != tdb->transaction->hash_heads[h+1]) {
+ break;
+ }
+ }
+ (*chain) = h;
+}
+
+/*
+ out of bounds check during a transaction
+*/
+static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
+{
+ if (len <= tdb->map_size) {
+ return 0;
+ }
+ return TDB_ERRCODE(TDB_ERR_IO, -1);
+}
+
+/*
+ transaction version of tdb_expand().
+*/
+static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
+ tdb_off_t addition)
+{
+ /* add a write to the transaction elements, so subsequent
+ reads see the zero data */
+ if (transaction_write(tdb, size, NULL, addition) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ brlock during a transaction - ignore them
+*/
+int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
+ int rw_type, int lck_type, int probe, size_t len)
+{
+ return 0;
+}
+
+static const struct tdb_methods transaction_methods = {
+ transaction_read,
+ transaction_write,
+ transaction_next_hash_chain,
+ transaction_oob,
+ transaction_expand_file,
+ transaction_brlock
+};
+
+
+/*
+ start a tdb transaction. No token is returned, as only a single
+ transaction is allowed to be pending per tdb_context
+*/
+int tdb_transaction_start(struct tdb_context *tdb)
+{
+ /* some sanity checks */
+ if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n"));
+ tdb->ecode = TDB_ERR_EINVAL;
+ return -1;
+ }
+
+ /* cope with nested tdb_transaction_start() calls */
+ if (tdb->transaction != NULL) {
+ tdb->transaction->nesting++;
+ TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n",
+ tdb->transaction->nesting));
+ return 0;
+ }
+
+ if (tdb->num_locks != 0 || tdb->global_lock.count) {
+ /* the caller must not have any locks when starting a
+ transaction as otherwise we'll be screwed by lack
+ of nested locks in posix */
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ return -1;
+ }
+
+ if (tdb->travlocks.next != NULL) {
+ /* you cannot use transactions inside a traverse (although you can use
+ traverse inside a transaction) as otherwise you can end up with
+ deadlock */
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ return -1;
+ }
+
+ tdb->transaction = (struct tdb_transaction *)
+ calloc(sizeof(struct tdb_transaction), 1);
+ if (tdb->transaction == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ return -1;
+ }
+
+ /* get the transaction write lock. This is a blocking lock. As
+ discussed with Volker, there are a number of ways we could
+ make this async, which we will probably do in the future */
+ if (tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get transaction lock\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ SAFE_FREE(tdb->transaction);
+ return -1;
+ }
+
+ /* get a read lock from the freelist to the end of file. This
+ is upgraded to a write lock during the commit */
+ if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ goto fail;
+ }
+
+ /* setup a copy of the hash table heads so the hash scan in
+ traverse can be fast */
+ tdb->transaction->hash_heads = (u32 *)
+ calloc(tdb->header.hash_size+1, sizeof(u32));
+ if (tdb->transaction->hash_heads == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ goto fail;
+ }
+ if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
+ TDB_HASHTABLE_SIZE(tdb), 0) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n"));
+ tdb->ecode = TDB_ERR_IO;
+ goto fail;
+ }
+
+ /* make sure we know about any file expansions already done by
+ anyone else */
+ tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+ tdb->transaction->old_map_size = tdb->map_size;
+
+ /* finally hook the io methods, replacing them with
+ transaction specific methods */
+ tdb->transaction->io_methods = tdb->methods;
+ tdb->methods = &transaction_methods;
+
+ /* by calling this transaction write here, we ensure that we don't grow the
+ transaction linked list due to hash table updates */
+ if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
+ TDB_HASHTABLE_SIZE(tdb)) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
+ tdb->ecode = TDB_ERR_IO;
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
+ tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+ SAFE_FREE(tdb->transaction->hash_heads);
+ SAFE_FREE(tdb->transaction);
+ return -1;
+}
+
+
+/*
+ cancel the current transaction
+*/
+int tdb_transaction_cancel(struct tdb_context *tdb)
+{
+ if (tdb->transaction == NULL) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
+ return -1;
+ }
+
+ if (tdb->transaction->nesting != 0) {
+ tdb->transaction->transaction_error = 1;
+ tdb->transaction->nesting--;
+ return 0;
+ }
+
+ tdb->map_size = tdb->transaction->old_map_size;
+
+ /* free all the transaction elements */
+ while (tdb->transaction->elements) {
+ struct tdb_transaction_el *el = tdb->transaction->elements;
+ tdb->transaction->elements = el->next;
+ free(el->data);
+ free(el);
+ }
+
+ /* remove any global lock created during the transaction */
+ if (tdb->global_lock.count != 0) {
+ tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
+ tdb->global_lock.count = 0;
+ }
+
+ /* remove any locks created during the transaction */
+ if (tdb->num_locks != 0) {
+ int i;
+ for (i=0;i<tdb->num_lockrecs;i++) {
+ tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
+ F_UNLCK,F_SETLKW, 0, 1);
+ }
+ tdb->num_locks = 0;
+ }
+
+ /* restore the normal io methods */
+ tdb->methods = tdb->transaction->io_methods;
+
+ tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
+ tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+ SAFE_FREE(tdb->transaction->hash_heads);
+ SAFE_FREE(tdb->transaction);
+
+ return 0;
+}
+
+/*
+ sync to disk
+*/
+static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
+{
+ if (fsync(tdb->fd) != 0) {
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
+ return -1;
+ }
+#ifdef MS_SYNC
+ if (tdb->map_ptr) {
+ tdb_off_t moffset = offset & ~(tdb->page_size-1);
+ if (msync(moffset + (char *)tdb->map_ptr,
+ length + (offset - moffset), MS_SYNC) != 0) {
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n",
+ strerror(errno)));
+ return -1;
+ }
+ }
+#endif
+ return 0;
+}
+
+
+/*
+ work out how much space the linearised recovery data will consume
+*/
+static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
+{
+ struct tdb_transaction_el *el;
+ tdb_len_t recovery_size = 0;
+
+ recovery_size = sizeof(u32);
+ for (el=tdb->transaction->elements;el;el=el->next) {
+ if (el->offset >= tdb->transaction->old_map_size) {
+ continue;
+ }
+ recovery_size += 2*sizeof(tdb_off_t) + el->length;
+ }
+
+ return recovery_size;
+}
+
+/*
+ allocate the recovery area, or use an existing recovery area if it is
+ large enough
+*/
+static int tdb_recovery_allocate(struct tdb_context *tdb,
+ tdb_len_t *recovery_size,
+ tdb_off_t *recovery_offset,
+ tdb_len_t *recovery_max_size)
+{
+ struct list_struct rec;
+ const struct tdb_methods *methods = tdb->transaction->io_methods;
+ tdb_off_t recovery_head;
+
+ if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n"));
+ return -1;
+ }
+
+ rec.rec_len = 0;
+
+ if (recovery_head != 0 &&
+ methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
+ return -1;
+ }
+
+ *recovery_size = tdb_recovery_size(tdb);
+
+ if (recovery_head != 0 && *recovery_size <= rec.rec_len) {
+ /* it fits in the existing area */
+ *recovery_max_size = rec.rec_len;
+ *recovery_offset = recovery_head;
+ return 0;
+ }
+
+ /* we need to free up the old recovery area, then allocate a
+ new one at the end of the file. Note that we cannot use
+ tdb_allocate() to allocate the new one as that might return
+ us an area that is being currently used (as of the start of
+ the transaction) */
+ if (recovery_head != 0) {
+ if (tdb_free(tdb, recovery_head, &rec) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n"));
+ return -1;
+ }
+ }
+
+ /* the tdb_free() call might have increased the recovery size */
+ *recovery_size = tdb_recovery_size(tdb);
+
+ /* round up to a multiple of page size */
+ *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
+ *recovery_offset = tdb->map_size;
+ recovery_head = *recovery_offset;
+
+ if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
+ (tdb->map_size - tdb->transaction->old_map_size) +
+ sizeof(rec) + *recovery_max_size) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n"));
+ return -1;
+ }
+
+ /* remap the file (if using mmap) */
+ methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+
+ /* we have to reset the old map size so that we don't try to expand the file
+ again in the transaction commit, which would destroy the recovery area */
+ tdb->transaction->old_map_size = tdb->map_size;
+
+ /* write the recovery header offset and sync - we can sync without a race here
+ as the magic ptr in the recovery record has not been set */
+ CONVERT(recovery_head);
+ if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD,
+ &recovery_head, sizeof(tdb_off_t)) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ setup the recovery data that will be used on a crash during commit
+*/
+static int transaction_setup_recovery(struct tdb_context *tdb,
+ tdb_off_t *magic_offset)
+{
+ struct tdb_transaction_el *el;
+ tdb_len_t recovery_size;
+ unsigned char *data, *p;
+ const struct tdb_methods *methods = tdb->transaction->io_methods;
+ struct list_struct *rec;
+ tdb_off_t recovery_offset, recovery_max_size;
+ tdb_off_t old_map_size = tdb->transaction->old_map_size;
+ u32 magic, tailer;
+
+ /*
+ check that the recovery area has enough space
+ */
+ if (tdb_recovery_allocate(tdb, &recovery_size,
+ &recovery_offset, &recovery_max_size) == -1) {
+ return -1;
+ }
+
+ data = (unsigned char *)malloc(recovery_size + sizeof(*rec));
+ if (data == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ return -1;
+ }
+
+ rec = (struct list_struct *)data;
+ memset(rec, 0, sizeof(*rec));
+
+ rec->magic = 0;
+ rec->data_len = recovery_size;
+ rec->rec_len = recovery_max_size;
+ rec->key_len = old_map_size;
+ CONVERT(rec);
+
+ /* build the recovery data into a single blob to allow us to do a single
+ large write, which should be more efficient */
+ p = data + sizeof(*rec);
+ for (el=tdb->transaction->elements;el;el=el->next) {
+ if (el->offset >= old_map_size) {
+ continue;
+ }
+ if (el->offset + el->length > tdb->transaction->old_map_size) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n"));
+ free(data);
+ tdb->ecode = TDB_ERR_CORRUPT;
+ return -1;
+ }
+ memcpy(p, &el->offset, 4);
+ memcpy(p+4, &el->length, 4);
+ if (DOCONV()) {
+ tdb_convert(p, 8);
+ }
+ /* the recovery area contains the old data, not the
+ new data, so we have to call the original tdb_read
+ method to get it */
+ if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) {
+ free(data);
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+ p += 8 + el->length;
+ }
+
+ /* and the tailer */
+ tailer = sizeof(*rec) + recovery_max_size;
+ memcpy(p, &tailer, 4);
+ CONVERT(p);
+
+ /* write the recovery data to the recovery area */
+ if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n"));
+ free(data);
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ /* as we don't have ordered writes, we have to sync the recovery
+ data before we update the magic to indicate that the recovery
+ data is present */
+ if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) {
+ free(data);
+ return -1;
+ }
+
+ free(data);
+
+ magic = TDB_RECOVERY_MAGIC;
+ CONVERT(magic);
+
+ *magic_offset = recovery_offset + offsetof(struct list_struct, magic);
+
+ if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ /* ensure the recovery magic marker is on disk */
+ if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ commit the current transaction
+*/
+int tdb_transaction_commit(struct tdb_context *tdb)
+{
+ const struct tdb_methods *methods;
+ tdb_off_t magic_offset = 0;
+ u32 zero = 0;
+
+ if (tdb->transaction == NULL) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
+ return -1;
+ }
+
+ if (tdb->transaction->transaction_error) {
+ tdb->ecode = TDB_ERR_IO;
+ tdb_transaction_cancel(tdb);
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n"));
+ return -1;
+ }
+
+ if (tdb->transaction->nesting != 0) {
+ tdb->transaction->nesting--;
+ return 0;
+ }
+
+ /* check for a null transaction */
+ if (tdb->transaction->elements == NULL) {
+ tdb_transaction_cancel(tdb);
+ return 0;
+ }
+
+ methods = tdb->transaction->io_methods;
+
+ /* if there are any locks pending then the caller has not
+ nested their locks properly, so fail the transaction */
+ if (tdb->num_locks || tdb->global_lock.count) {
+ tdb->ecode = TDB_ERR_LOCK;
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n"));
+ tdb_transaction_cancel(tdb);
+ return -1;
+ }
+
+ /* upgrade the main transaction lock region to a write lock */
+ if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ tdb_transaction_cancel(tdb);
+ return -1;
+ }
+
+ /* get the global lock - this prevents new users attaching to the database
+ during the commit */
+ if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ tdb_transaction_cancel(tdb);
+ return -1;
+ }
+
+ if (!(tdb->flags & TDB_NOSYNC)) {
+ /* write the recovery data to the end of the file */
+ if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n"));
+ tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+ tdb_transaction_cancel(tdb);
+ return -1;
+ }
+ }
+
+ /* expand the file to the new size if needed */
+ if (tdb->map_size != tdb->transaction->old_map_size) {
+ if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
+ tdb->map_size -
+ tdb->transaction->old_map_size) == -1) {
+ tdb->ecode = TDB_ERR_IO;
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
+ tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+ tdb_transaction_cancel(tdb);
+ return -1;
+ }
+ tdb->map_size = tdb->transaction->old_map_size;
+ methods->tdb_oob(tdb, tdb->map_size + 1, 1);
+ }
+
+ /* perform all the writes */
+ while (tdb->transaction->elements) {
+ struct tdb_transaction_el *el = tdb->transaction->elements;
+
+ if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
+
+ /* we've overwritten part of the data and
+ possibly expanded the file, so we need to
+ run the crash recovery code */
+ tdb->methods = methods;
+ tdb_transaction_recover(tdb);
+
+ tdb_transaction_cancel(tdb);
+ tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
+ return -1;
+ }
+ tdb->transaction->elements = el->next;
+ free(el->data);
+ free(el);
+ }
+
+ if (!(tdb->flags & TDB_NOSYNC)) {
+ /* ensure the new data is on disk */
+ if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
+ return -1;
+ }
+
+ /* remove the recovery marker */
+ if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n"));
+ return -1;
+ }
+
+ /* ensure the recovery marker has been removed on disk */
+ if (transaction_sync(tdb, magic_offset, 4) == -1) {
+ return -1;
+ }
+ }
+
+ tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+ /*
+ TODO: maybe write to some dummy hdr field, or write to magic
+ offset without mmap, before the last sync, instead of the
+ utime() call
+ */
+
+ /* on some systems (like Linux 2.6.x) changes via mmap/msync
+ don't change the mtime of the file, this means the file may
+ not be backed up (as tdb rounding to block sizes means that
+ file size changes are quite rare too). The following forces
+ mtime changes when a transaction completes */
+#ifdef HAVE_UTIME
+ utime(tdb->name, NULL);
+#endif
+
+ /* use a transaction cancel to free memory and remove the
+ transaction locks */
+ tdb_transaction_cancel(tdb);
+ return 0;
+}
+
+
+/*
+ recover from an aborted transaction. Must be called with exclusive
+ database write access already established (including the global
+ lock to prevent new processes attaching)
+*/
+int tdb_transaction_recover(struct tdb_context *tdb)
+{
+ tdb_off_t recovery_head, recovery_eof;
+ unsigned char *data, *p;
+ u32 zero = 0;
+ struct list_struct rec;
+
+ /* find the recovery area */
+ if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ if (recovery_head == 0) {
+ /* we have never allocated a recovery record */
+ return 0;
+ }
+
+ /* read the recovery record */
+ if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
+ sizeof(rec), DOCONV()) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ if (rec.magic != TDB_RECOVERY_MAGIC) {
+ /* there is no valid recovery data */
+ return 0;
+ }
+
+ if (tdb->read_only) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n"));
+ tdb->ecode = TDB_ERR_CORRUPT;
+ return -1;
+ }
+
+ recovery_eof = rec.key_len;
+
+ data = (unsigned char *)malloc(rec.data_len);
+ if (data == NULL) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n"));
+ tdb->ecode = TDB_ERR_OOM;
+ return -1;
+ }
+
+ /* read the full recovery data */
+ if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
+ rec.data_len, 0) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ /* recover the file data */
+ p = data;
+ while (p+8 < data + rec.data_len) {
+ u32 ofs, len;
+ if (DOCONV()) {
+ tdb_convert(p, 8);
+ }
+ memcpy(&ofs, p, 4);
+ memcpy(&len, p+4, 4);
+
+ if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) {
+ free(data);
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+ p += 8 + len;
+ }
+
+ free(data);
+
+ if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ /* if the recovery area is after the recovered eof then remove it */
+ if (recovery_eof <= recovery_head) {
+ if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+ }
+
+ /* remove the recovery magic */
+ if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic),
+ &zero) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ /* reduce the file size to the old size */
+ tdb_munmap(tdb);
+ if (ftruncate(tdb->fd, recovery_eof) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+ tdb->map_size = recovery_eof;
+ tdb_mmap(tdb);
+
+ if (transaction_sync(tdb, 0, recovery_eof) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n"));
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+
+ TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n",
+ recovery_eof));
+
+ /* all done */
+ return 0;
+}
diff --git a/source/tdb/common/traverse.c b/source/tdb/common/traverse.c
new file mode 100644
index 00000000000..6d3b111479c
--- /dev/null
+++ b/source/tdb/common/traverse.c
@@ -0,0 +1,335 @@
+ /*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2005
+ Copyright (C) Paul `Rusty' Russell 2000
+ Copyright (C) Jeremy Allison 2000-2003
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "tdb_private.h"
+
+/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */
+static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock,
+ struct list_struct *rec)
+{
+ int want_next = (tlock->off != 0);
+
+ /* Lock each chain from the start one. */
+ for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
+ if (!tlock->off && tlock->hash != 0) {
+ /* this is an optimisation for the common case where
+ the hash chain is empty, which is particularly
+ common for the use of tdb with ldb, where large
+ hashes are used. In that case we spend most of our
+ time in tdb_brlock(), locking empty hash chains.
+
+ To avoid this, we do an unlocked pre-check to see
+ if the hash chain is empty before starting to look
+ inside it. If it is empty then we can avoid that
+ hash chain. If it isn't empty then we can't believe
+ the value we get back, as we read it without a
+ lock, so instead we get the lock and re-fetch the
+ value below.
+
+ Notice that not doing this optimisation on the
+ first hash chain is critical. We must guarantee
+ that we have done at least one fcntl lock at the
+ start of a search to guarantee that memory is
+ coherent on SMP systems. If records are added by
+ others during the search then thats OK, and we
+ could possibly miss those with this trick, but we
+ could miss them anyway without this trick, so the
+ semantics don't change.
+
+ With a non-indexed ldb search this trick gains us a
+ factor of around 80 in speed on a linux 2.6.x
+ system (testing using ldbtest).
+ */
+ tdb->methods->next_hash_chain(tdb, &tlock->hash);
+ if (tlock->hash == tdb->header.hash_size) {
+ continue;
+ }
+ }
+
+ if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1)
+ return -1;
+
+ /* No previous record? Start at top of chain. */
+ if (!tlock->off) {
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
+ &tlock->off) == -1)
+ goto fail;
+ } else {
+ /* Otherwise unlock the previous record. */
+ if (tdb_unlock_record(tdb, tlock->off) != 0)
+ goto fail;
+ }
+
+ if (want_next) {
+ /* We have offset of old record: grab next */
+ if (tdb_rec_read(tdb, tlock->off, rec) == -1)
+ goto fail;
+ tlock->off = rec->next;
+ }
+
+ /* Iterate through chain */
+ while( tlock->off) {
+ tdb_off_t current;
+ if (tdb_rec_read(tdb, tlock->off, rec) == -1)
+ goto fail;
+
+ /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
+ if (tlock->off == rec->next) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n"));
+ goto fail;
+ }
+
+ if (!TDB_DEAD(rec)) {
+ /* Woohoo: we found one! */
+ if (tdb_lock_record(tdb, tlock->off) != 0)
+ goto fail;
+ return tlock->off;
+ }
+
+ /* Try to clean dead ones from old traverses */
+ current = tlock->off;
+ tlock->off = rec->next;
+ if (!(tdb->read_only || tdb->traverse_read) &&
+ tdb_do_delete(tdb, current, rec) != 0)
+ goto fail;
+ }
+ tdb_unlock(tdb, tlock->hash, tlock->lock_rw);
+ want_next = 0;
+ }
+ /* We finished iteration without finding anything */
+ return TDB_ERRCODE(TDB_SUCCESS, 0);
+
+ fail:
+ tlock->off = 0;
+ if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n"));
+ return -1;
+}
+
+/* traverse the entire database - calling fn(tdb, key, data) on each element.
+ return -1 on error or the record count traversed
+ if fn is NULL then it is not called
+ a non-zero return value from fn() indicates that the traversal should stop
+ */
+static int tdb_traverse_internal(struct tdb_context *tdb,
+ tdb_traverse_func fn, void *private_data,
+ struct tdb_traverse_lock *tl)
+{
+ TDB_DATA key, dbuf;
+ struct list_struct rec;
+ int ret, count = 0;
+
+ /* This was in the initializaton, above, but the IRIX compiler
+ * did not like it. crh
+ */
+ tl->next = tdb->travlocks.next;
+
+ /* fcntl locks don't stack: beware traverse inside traverse */
+ tdb->travlocks.next = tl;
+
+ /* tdb_next_lock places locks on the record returned, and its chain */
+ while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
+ count++;
+ /* now read the full record */
+ key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec),
+ rec.key_len + rec.data_len);
+ if (!key.dptr) {
+ ret = -1;
+ if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0)
+ goto out;
+ if (tdb_unlock_record(tdb, tl->off) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
+ goto out;
+ }
+ key.dsize = rec.key_len;
+ dbuf.dptr = key.dptr + rec.key_len;
+ dbuf.dsize = rec.data_len;
+
+ /* Drop chain lock, call out */
+ if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
+ ret = -1;
+ SAFE_FREE(key.dptr);
+ goto out;
+ }
+ if (fn && fn(tdb, key, dbuf, private_data)) {
+ /* They want us to terminate traversal */
+ ret = count;
+ if (tdb_unlock_record(tdb, tl->off) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));;
+ ret = -1;
+ }
+ SAFE_FREE(key.dptr);
+ goto out;
+ }
+ SAFE_FREE(key.dptr);
+ }
+out:
+ tdb->travlocks.next = tl->next;
+ if (ret < 0)
+ return -1;
+ else
+ return count;
+}
+
+
+/*
+ a write style traverse - temporarily marks the db read only
+*/
+int tdb_traverse_read(struct tdb_context *tdb,
+ tdb_traverse_func fn, void *private_data)
+{
+ struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
+ int ret;
+
+ /* we need to get a read lock on the transaction lock here to
+ cope with the lock ordering semantics of solaris10 */
+ if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse_read: failed to get transaction lock\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ return -1;
+ }
+
+ tdb->traverse_read++;
+ ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
+ tdb->traverse_read--;
+
+ tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+ return ret;
+}
+
+/*
+ a write style traverse - needs to get the transaction lock to
+ prevent deadlocks
+*/
+int tdb_traverse(struct tdb_context *tdb,
+ tdb_traverse_func fn, void *private_data)
+{
+ struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
+ int ret;
+
+ if (tdb->read_only || tdb->traverse_read) {
+ return tdb_traverse_read(tdb, fn, private_data);
+ }
+
+ if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse: failed to get transaction lock\n"));
+ tdb->ecode = TDB_ERR_LOCK;
+ return -1;
+ }
+
+ ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
+
+ tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
+
+ return ret;
+}
+
+
+/* find the first entry in the database and return its key */
+TDB_DATA tdb_firstkey(struct tdb_context *tdb)
+{
+ TDB_DATA key;
+ struct list_struct rec;
+
+ /* release any old lock */
+ if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0)
+ return tdb_null;
+ tdb->travlocks.off = tdb->travlocks.hash = 0;
+ tdb->travlocks.lock_rw = F_RDLCK;
+
+ if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
+ return tdb_null;
+ /* now read the key */
+ key.dsize = rec.key_len;
+ key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
+ if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
+ return key;
+}
+
+/* find the next entry in the database, returning its key */
+TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
+{
+ u32 oldhash;
+ TDB_DATA key = tdb_null;
+ struct list_struct rec;
+ char *k = NULL;
+
+ /* Is locked key the old key? If so, traverse will be reliable. */
+ if (tdb->travlocks.off) {
+ if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
+ return tdb_null;
+ if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1
+ || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
+ rec.key_len))
+ || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
+ /* No, it wasn't: unlock it and start from scratch */
+ if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) {
+ SAFE_FREE(k);
+ return tdb_null;
+ }
+ if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
+ SAFE_FREE(k);
+ return tdb_null;
+ }
+ tdb->travlocks.off = 0;
+ }
+
+ SAFE_FREE(k);
+ }
+
+ if (!tdb->travlocks.off) {
+ /* No previous element: do normal find, and lock record */
+ tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
+ if (!tdb->travlocks.off)
+ return tdb_null;
+ tdb->travlocks.hash = BUCKET(rec.full_hash);
+ if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
+ return tdb_null;
+ }
+ }
+ oldhash = tdb->travlocks.hash;
+
+ /* Grab next record: locks chain and returned record,
+ unlocks old record */
+ if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
+ key.dsize = rec.key_len;
+ key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
+ key.dsize);
+ /* Unlock the chain of this new record */
+ if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
+ }
+ /* Unlock the chain of old record */
+ if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
+ return key;
+}
+
diff --git a/source/tdb/config.m4 b/source/tdb/config.m4
new file mode 100644
index 00000000000..a37f36b29e0
--- /dev/null
+++ b/source/tdb/config.m4
@@ -0,0 +1,58 @@
+dnl find the tdb sources. This is meant to work both for
+dnl tdb standalone builds, and builds of packages using tdb
+tdbdir=""
+tdbpaths="$srcdir $srcdir/lib/tdb $srcdir/tdb $srcdir/../tdb"
+for d in $tdbpaths; do
+ if test -f "$d/common/tdb.c"; then
+ tdbdir="$d"
+ AC_SUBST(tdbdir)
+ break;
+ fi
+done
+if test x"$tdbdir" = "x"; then
+ AC_MSG_ERROR([cannot find tdb source in $tdbpaths])
+fi
+TDBOBJ="common/tdb.o common/dump.o common/transaction.o common/error.o common/traverse.o"
+TDBOBJ="$TDBOBJ common/freelist.o common/freelistcheck.o common/io.o common/lock.o common/open.o"
+AC_SUBST(TDBOBJ)
+
+libreplacedir=../lib/replace
+AC_SUBST(libreplacedir)
+
+AC_CHECK_FUNCS(mmap pread pwrite getpagesize utime)
+AC_CHECK_HEADERS(getopt.h sys/select.h sys/time.h)
+
+AC_HAVE_DECL(pread, [#include <unistd.h>])
+AC_HAVE_DECL(pwrite, [#include <unistd.h>])
+
+AC_MSG_CHECKING([for Python])
+
+PYTHON=
+
+AC_ARG_WITH(python,
+[ --with-python=PYTHONNAME build Python libraries],
+[ case "${withval-python}" in
+ yes)
+ PYTHON=python
+ ;;
+ no)
+ PYTHON=
+ ;;
+ *)
+ PYTHON=${withval-python}
+ ;;
+ esac ])
+
+if test x"$PYTHON" != "x"; then
+ incdir=`python -c 'import sys; print "%s/include/python%d.%d" % (sys.prefix, sys.version_info[[0]], sys.version_info[[1]])'`
+ CPPFLAGS="$CPPFLAGS -I $incdir"
+fi
+
+if test x"$PYTHON" != "x"; then
+ AC_MSG_RESULT([${withval-python}])
+else
+ SMB_ENABLE(swig_tdb, NO)
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(PYTHON)
diff --git a/source/tdb/config.mk b/source/tdb/config.mk
new file mode 100644
index 00000000000..c5d1a339907
--- /dev/null
+++ b/source/tdb/config.mk
@@ -0,0 +1,70 @@
+################################################
+# Start SUBSYSTEM LIBTDB
+[LIBRARY::LIBTDB]
+VERSION = 0.0.1
+SO_VERSION = 0
+DESCRIPTION = Trivial Database Library
+OBJ_FILES = \
+ common/tdb.o common/dump.o common/io.o common/lock.o \
+ common/open.o common/traverse.o common/freelist.o \
+ common/error.o common/transaction.o common/tdbutil.o
+CFLAGS = -Ilib/tdb/include
+PUBLIC_HEADERS = include/tdb.h
+#
+# End SUBSYSTEM ldb
+################################################
+
+################################################
+# Start BINARY tdbtool
+[BINARY::tdbtool]
+INSTALLDIR = BINDIR
+ENABLE = NO
+OBJ_FILES= \
+ tools/tdbtool.o
+PRIVATE_DEPENDENCIES = \
+ LIBTDB
+# End BINARY tdbtool
+################################################
+
+################################################
+# Start BINARY tdbtorture
+[BINARY::tdbtorture]
+INSTALLDIR = BINDIR
+OBJ_FILES= \
+ tools/tdbtorture.o
+PRIVATE_DEPENDENCIES = \
+ LIBTDB
+# End BINARY tdbtorture
+################################################
+
+################################################
+# Start BINARY tdbdump
+[BINARY::tdbdump]
+INSTALLDIR = BINDIR
+OBJ_FILES= \
+ tools/tdbdump.o
+PRIVATE_DEPENDENCIES = \
+ LIBTDB
+# End BINARY tdbdump
+################################################
+
+################################################
+# Start BINARY tdbbackup
+[BINARY::tdbbackup]
+INSTALLDIR = BINDIR
+ENABLE = NO
+OBJ_FILES= \
+ tools/tdbbackup.o
+PRIVATE_DEPENDENCIES = \
+ LIBTDB
+# End BINARY tdbbackup
+################################################
+
+#######################
+# Start LIBRARY swig_tdb
+[LIBRARY::swig_tdb]
+LIBRARY_REALNAME = swig/_tdb.$(SHLIBEXT)
+OBJ_FILES = swig/tdb_wrap.o
+PUBLIC_DEPENDENCIES = LIBTDB DYNCONFIG
+# End LIBRARY swig_tdb
+#######################
diff --git a/source/tdb/configure.in b/source/tdb/configure.in
new file mode 100644
index 00000000000..0a72af20d94
--- /dev/null
+++ b/source/tdb/configure.in
@@ -0,0 +1,13 @@
+AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""])
+AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""])
+AC_DEFUN([SMB_ENABLE], [echo -n ""])
+AC_INIT(include/tdb.h)
+AC_CONFIG_HEADER(include/config.h)
+AC_PROG_CC
+AC_SYS_LARGEFILE
+AC_CHECK_SIZEOF(off_t,cross)
+AC_CHECK_SIZEOF(size_t,cross)
+AC_CHECK_SIZEOF(ssize_t,cross)
+AC_FUNC_MMAP
+sinclude(config.m4)
+AC_OUTPUT(Makefile tdb.pc)
diff --git a/source/tdb/README b/source/tdb/docs/README
index fac3eacb4db..b31ce36ab14 100644
--- a/source/tdb/README
+++ b/source/tdb/docs/README
@@ -15,7 +15,6 @@ Compilation
-----------
add HAVE_MMAP=1 to use mmap instead of read/write
-add TDB_DEBUG=1 for verbose debug info
add NOLOCK=1 to disable locking code
Testing
@@ -41,6 +40,7 @@ The interface is very similar to gdbm except for the following:
- no tdbm_reorganise() function
- no tdbm_sync() function. No operations are cached in the library anyway
- added a tdb_traverse() function for traversing the whole database
+- added transactions support
A general rule for using tdb is that the caller frees any returned
TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA
@@ -68,6 +68,19 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
memory. The filename is ignored in this case.
TDB_NOLOCK - don't do any locking
TDB_NOMMAP - don't use mmap
+ TDB_NOSYNC - don't synchronise transactions to disk
+
+----------------------------------------------------------------------
+TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode,
+ tdb_log_func log_fn,
+ tdb_hash_func hash_fn)
+
+This is like tdb_open(), but allows you to pass an initial logging and
+hash function. Be careful when passing a hash function - all users of
+the database must use the same hash function or you will get data
+corruption.
+
----------------------------------------------------------------------
char *tdb_error(TDB_CONTEXT *tdb);
@@ -114,7 +127,25 @@ int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
if fn is NULL then it is not called
- a non-zero return value from fn() indicates that the traversal should stop
+ a non-zero return value from fn() indicates that the traversal
+ should stop. Traversal callbacks may not start transactions.
+
+----------------------------------------------------------------------
+int tdb_traverse_read(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
+ TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
+
+ traverse the entire database - calling fn(tdb, key, data, state) on
+ each element, but marking the database read only during the
+ traversal, so any write operations will fail. This allows tdb to
+ use read locks, which increases the parallelism possible during the
+ traversal.
+
+ return -1 on error or the record count traversed
+
+ if fn is NULL then it is not called
+
+ a non-zero return value from fn() indicates that the traversal
+ should stop. Traversal callbacks may not start transactions.
----------------------------------------------------------------------
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
@@ -165,3 +196,40 @@ int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
unlock one hash chain
+
+----------------------------------------------------------------------
+int tdb_transaction_start(TDB_CONTEXT *tdb)
+
+ start a transaction. All operations after the transaction start can
+ either be committed with tdb_transaction_commit() or cancelled with
+ tdb_transaction_cancel().
+
+ If you call tdb_transaction_start() again on the same tdb context
+ while a transaction is in progress, then the same transaction
+ buffer is re-used. The number of tdb_transaction_{commit,cancel}
+ operations must match the number of successful
+ tdb_transaction_start() calls.
+
+ Note that transactions are by default disk synchronous, and use a
+ recover area in the database to automatically recover the database
+ on the next open if the system crashes during a transaction. You
+ can disable the synchronous transaction recovery setup using the
+ TDB_NOSYNC flag, which will greatly speed up operations at the risk
+ of corrupting your database if the system crashes.
+
+ Operations made within a transaction are not visible to other users
+ of the database until a successful commit.
+
+----------------------------------------------------------------------
+int tdb_transaction_cancel(TDB_CONTEXT *tdb)
+
+ cancel a current transaction, discarding all write and lock
+ operations that have been made since the transaction started.
+
+
+----------------------------------------------------------------------
+int tdb_transaction_commit(TDB_CONTEXT *tdb)
+
+ commit a current transaction, updating the database and releasing
+ the transaction locks.
+
diff --git a/source/tdb/tdb.magic b/source/tdb/docs/tdb.magic
index f5619e7327e..f5619e7327e 100644
--- a/source/tdb/tdb.magic
+++ b/source/tdb/docs/tdb.magic
diff --git a/source/tdb/include/tdb.h b/source/tdb/include/tdb.h
new file mode 100644
index 00000000000..a0f6f983824
--- /dev/null
+++ b/source/tdb/include/tdb.h
@@ -0,0 +1,151 @@
+#ifndef __TDB_H__
+#define __TDB_H__
+
+/*
+ Unix SMB/CIFS implementation.
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2004
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* flags to tdb_store() */
+#define TDB_REPLACE 1
+#define TDB_INSERT 2
+#define TDB_MODIFY 3
+
+/* flags for tdb_open() */
+#define TDB_DEFAULT 0 /* just a readability place holder */
+#define TDB_CLEAR_IF_FIRST 1
+#define TDB_INTERNAL 2 /* don't store on disk */
+#define TDB_NOLOCK 4 /* don't do any locking */
+#define TDB_NOMMAP 8 /* don't use mmap */
+#define TDB_CONVERT 16 /* convert endian (internal use) */
+#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
+#define TDB_NOSYNC 64 /* don't use synchronous transactions */
+#define TDB_SEQNUM 128 /* maintain a sequence number */
+
+#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
+
+/* error codes */
+enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
+ TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
+ TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY};
+
+/* debugging uses one of the following levels */
+enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR,
+ TDB_DEBUG_WARNING, TDB_DEBUG_TRACE};
+
+typedef struct TDB_DATA {
+ char *dptr;
+ size_t dsize;
+} TDB_DATA;
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* this is the context structure that is returned from a db open */
+typedef struct tdb_context TDB_CONTEXT;
+
+typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *);
+typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4);
+typedef unsigned int (*tdb_hash_func)(TDB_DATA *key);
+
+struct tdb_logging_context {
+ tdb_log_func log_fn;
+ void *log_private;
+};
+
+struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode);
+struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
+ int open_flags, mode_t mode,
+ const struct tdb_logging_context *log_ctx,
+ tdb_hash_func hash_fn);
+
+int tdb_reopen(struct tdb_context *tdb);
+int tdb_reopen_all(int parent_longlived);
+void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx);
+enum TDB_ERROR tdb_error(struct tdb_context *tdb);
+const char *tdb_errorstr(struct tdb_context *tdb);
+TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
+int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
+ int (*parser)(TDB_DATA key, TDB_DATA data,
+ void *private_data),
+ void *private_data);
+int tdb_delete(struct tdb_context *tdb, TDB_DATA key);
+int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf);
+int tdb_close(struct tdb_context *tdb);
+TDB_DATA tdb_firstkey(struct tdb_context *tdb);
+TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key);
+int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *);
+int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *);
+int tdb_exists(struct tdb_context *tdb, TDB_DATA key);
+int tdb_lockall(struct tdb_context *tdb);
+int tdb_unlockall(struct tdb_context *tdb);
+int tdb_lockall_read(struct tdb_context *tdb);
+int tdb_unlockall_read(struct tdb_context *tdb);
+const char *tdb_name(struct tdb_context *tdb);
+int tdb_fd(struct tdb_context *tdb);
+tdb_log_func tdb_log_fn(struct tdb_context *tdb);
+void *tdb_get_logging_private(struct tdb_context *tdb);
+int tdb_transaction_start(struct tdb_context *tdb);
+int tdb_transaction_commit(struct tdb_context *tdb);
+int tdb_transaction_cancel(struct tdb_context *tdb);
+int tdb_transaction_recover(struct tdb_context *tdb);
+int tdb_get_seqnum(struct tdb_context *tdb);
+int tdb_hash_size(struct tdb_context *tdb);
+size_t tdb_map_size(struct tdb_context *tdb);
+int tdb_get_flags(struct tdb_context *tdb);
+
+/* Low level locking functions: use with care */
+int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
+int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
+
+/* Debug functions. Not used in production. */
+void tdb_dump_all(struct tdb_context *tdb);
+int tdb_printfreelist(struct tdb_context *tdb);
+int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
+
+extern TDB_DATA tdb_null;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* tdb.h */
diff --git a/source/tdb/tdbback.h b/source/tdb/include/tdbback.h
index 7ebeaa494d6..69d3bb6f91a 100644
--- a/source/tdb/tdbback.h
+++ b/source/tdb/include/tdbback.h
@@ -19,5 +19,5 @@
*/
char *add_suffix(const char *name, const char *suffix);
-int backup_tdb(const char *old_name, const char *new_name);
+int backup_tdb(const char *old_name, const char *new_name, int hash_size);
int verify_tdb(const char *fname, const char *bak_name);
diff --git a/source/tdb/include/tdbconfig.h.in b/source/tdb/include/tdbconfig.h.in
new file mode 100644
index 00000000000..d6d2c09b3c8
--- /dev/null
+++ b/source/tdb/include/tdbconfig.h.in
@@ -0,0 +1,58 @@
+/* include/tdbconfig.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
diff --git a/source/tdb/spinlock.c b/source/tdb/spinlock.c
deleted file mode 100644
index e42a6901c71..00000000000
--- a/source/tdb/spinlock.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- trivial database library
-
- Copyright (C) Anton Blanchard 2001
-
- ** NOTE! The following LGPL license applies to the tdb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef STANDALONE
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <signal.h>
-#include "tdb.h"
-#include "spinlock.h"
-
-#define DEBUG
-#else
-#include "includes.h"
-#endif
-
-#ifdef USE_SPINLOCKS
-
-/*
- * ARCH SPECIFIC
- */
-
-#if defined(SPARC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int result;
-
- asm volatile("ldstub [%1], %0"
- : "=r" (result)
- : "r" (lock)
- : "memory");
-
- return (result == 0) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#elif defined(POWERPC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int result;
-
- __asm__ __volatile__(
-"1: lwarx %0,0,%1\n\
- cmpwi 0,%0,0\n\
- li %0,0\n\
- bne- 2f\n\
- li %0,1\n\
- stwcx. %0,0,%1\n\
- bne- 1b\n\
- isync\n\
-2:" : "=&r"(result)
- : "r"(lock)
- : "cr0", "memory");
-
- return (result == 1) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("eieio":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#elif defined(INTEL_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- int oldval;
-
- asm volatile("xchgl %0,%1"
- : "=r" (oldval), "=m" (*lock)
- : "0" (0)
- : "memory");
-
- return oldval > 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 1;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 1;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 1);
-}
-
-#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730)
-
-/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See
- * sync(3) for the details of the intrinsic operations.
- *
- * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro.
- */
-
-#ifdef STANDALONE
-
-/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */
-#define inline __inline
-
-#endif /* STANDALONE */
-
-/* Returns 0 if the lock is acquired, EBUSY otherwise. */
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int val;
- val = __lock_test_and_set(lock, 1);
- return val == 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- __lock_release(lock);
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- __lock_release(lock);
-}
-
-/* Returns 1 if the lock is held, 0 otherwise. */
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- unsigned int val;
- val = __add_and_fetch(lock, 0);
- return val;
-}
-
-#elif defined(MIPS_SPINLOCKS)
-
-static inline unsigned int load_linked(unsigned long addr)
-{
- unsigned int res;
-
- __asm__ __volatile__("ll\t%0,(%1)"
- : "=r" (res)
- : "r" (addr));
-
- return res;
-}
-
-static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
-{
- unsigned int res;
-
- __asm__ __volatile__("sc\t%0,(%2)"
- : "=r" (res)
- : "0" (value), "r" (addr));
- return res;
-}
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int mw;
-
- do {
- mw = load_linked(lock);
- if (mw)
- return EBUSY;
- } while (!store_conditional(lock, 1));
-
- asm volatile("":::"memory");
-
- return 0;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#else
-#error Need to implement spinlock code in spinlock.c
-#endif
-
-/*
- * OS SPECIFIC
- */
-
-static void yield_cpu(void)
-{
- struct timespec tm;
-
-#ifdef USE_SCHED_YIELD
- sched_yield();
-#else
- /* Linux will busy loop for delays < 2ms on real time tasks */
- tm.tv_sec = 0;
- tm.tv_nsec = 2000000L + 1;
- nanosleep(&tm, NULL);
-#endif
-}
-
-/*
- * GENERIC
- */
-
-static int smp_machine = 0;
-
-static inline void __spin_lock(spinlock_t *lock)
-{
- int ntries = 0;
-
- while(__spin_trylock(lock)) {
- while(__spin_is_locked(lock)) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __read_lock(tdb_rwlock_t *rwlock)
-{
- int ntries = 0;
-
- while(1) {
- __spin_lock(&rwlock->lock);
-
- if (!(rwlock->count & RWLOCK_BIAS)) {
- rwlock->count++;
- __spin_unlock(&rwlock->lock);
- return;
- }
-
- __spin_unlock(&rwlock->lock);
-
- while(rwlock->count & RWLOCK_BIAS) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __write_lock(tdb_rwlock_t *rwlock)
-{
- int ntries = 0;
-
- while(1) {
- __spin_lock(&rwlock->lock);
-
- if (rwlock->count == 0) {
- rwlock->count |= RWLOCK_BIAS;
- __spin_unlock(&rwlock->lock);
- return;
- }
-
- __spin_unlock(&rwlock->lock);
-
- while(rwlock->count != 0) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __write_unlock(tdb_rwlock_t *rwlock)
-{
- __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
- if (!(rwlock->count & RWLOCK_BIAS))
- fprintf(stderr, "bug: write_unlock\n");
-#endif
-
- rwlock->count &= ~RWLOCK_BIAS;
- __spin_unlock(&rwlock->lock);
-}
-
-static void __read_unlock(tdb_rwlock_t *rwlock)
-{
- __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
- if (!rwlock->count)
- fprintf(stderr, "bug: read_unlock\n");
-
- if (rwlock->count & RWLOCK_BIAS)
- fprintf(stderr, "bug: read_unlock\n");
-#endif
-
- rwlock->count--;
- __spin_unlock(&rwlock->lock);
-}
-
-/* TDB SPECIFIC */
-
-/* lock a list in the database. list -1 is the alloc list */
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
- tdb_rwlock_t *rwlocks;
-
- if (!tdb->map_ptr) return -1;
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
- switch(rw_type) {
- case F_RDLCK:
- __read_lock(&rwlocks[list+1]);
- break;
-
- case F_WRLCK:
- __write_lock(&rwlocks[list+1]);
- break;
-
- default:
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- }
- return 0;
-}
-
-/* unlock the database. */
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
- tdb_rwlock_t *rwlocks;
-
- if (!tdb->map_ptr) return -1;
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
- switch(rw_type) {
- case F_RDLCK:
- __read_unlock(&rwlocks[list+1]);
- break;
-
- case F_WRLCK:
- __write_unlock(&rwlocks[list+1]);
- break;
-
- default:
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- }
-
- return 0;
-}
-
-int tdb_create_rwlocks(int fd, unsigned int hash_size)
-{
- unsigned size, i;
- tdb_rwlock_t *rwlocks;
-
- size = TDB_SPINLOCK_SIZE(hash_size);
- rwlocks = malloc(size);
- if (!rwlocks)
- return -1;
-
- for(i = 0; i < hash_size+1; i++) {
- __spin_lock_init(&rwlocks[i].lock);
- rwlocks[i].count = 0;
- }
-
- /* Write it out (appending to end) */
- if (write(fd, rwlocks, size) != size) {
- free(rwlocks);
- return -1;
- }
- smp_machine = this_is_smp();
- free(rwlocks);
- return 0;
-}
-
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
- tdb_rwlock_t *rwlocks;
- unsigned i;
-
- if (tdb->header.rwlocks == 0) return 0;
- if (!tdb->map_ptr) return -1;
-
- /* We're mmapped here */
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
- for(i = 0; i < tdb->header.hash_size+1; i++) {
- __spin_lock_init(&rwlocks[i].lock);
- rwlocks[i].count = 0;
- }
- return 0;
-}
-#else
-int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-
-/* Non-spinlock version: remove spinlock pointer */
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
- tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
- - (char *)&tdb->header);
-
- tdb->header.rwlocks = 0;
- if (lseek(tdb->fd, off, SEEK_SET) != off
- || write(tdb->fd, (void *)&tdb->header.rwlocks,
- sizeof(tdb->header.rwlocks))
- != sizeof(tdb->header.rwlocks))
- return -1;
- return 0;
-}
-#endif
diff --git a/source/tdb/spinlock.h b/source/tdb/spinlock.h
deleted file mode 100644
index 967fe37457f..00000000000
--- a/source/tdb/spinlock.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __SPINLOCK_H__
-#define __SPINLOCK_H__
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "tdb.h"
-
-#ifdef USE_SPINLOCKS
-
-#define RWLOCK_BIAS 0x1000UL
-
-/* OS SPECIFIC */
-#define MAX_BUSY_LOOPS 1000
-#undef USE_SCHED_YIELD
-
-/* ARCH SPECIFIC */
-/* We should make sure these are padded to a cache line */
-#if defined(SPARC_SPINLOCKS)
-typedef volatile char spinlock_t;
-#elif defined(POWERPC_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#elif defined(INTEL_SPINLOCKS)
-typedef volatile int spinlock_t;
-#elif defined(MIPS_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#else
-#error Need to implement spinlock code in spinlock.h
-#endif
-
-typedef struct {
- spinlock_t lock;
- volatile int count;
-} tdb_rwlock_t;
-
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_create_rwlocks(int fd, unsigned int hash_size);
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
-
-#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
-
-#else /* !USE_SPINLOCKS */
-#if 0
-#define tdb_create_rwlocks(fd, hash_size) 0
-#define tdb_spinlock(tdb, list, rw_type) (-1)
-#define tdb_spinunlock(tdb, list, rw_type) (-1)
-#else
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_create_rwlocks(int fd, unsigned int hash_size);
-#endif
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
-#define TDB_SPINLOCK_SIZE(hash_size) 0
-
-#endif
-
-#endif
diff --git a/source/tdb/swig/Tdb.py b/source/tdb/swig/Tdb.py
new file mode 100644
index 00000000000..aac7a90354d
--- /dev/null
+++ b/source/tdb/swig/Tdb.py
@@ -0,0 +1,116 @@
+"""Provide a more Pythonic and object-oriented interface to tdb."""
+
+#
+# Swig interface to Samba
+#
+# Copyright (C) Tim Potter 2006
+#
+# 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.
+#
+
+import os
+from tdb import *
+
+# Open flags
+
+DEFAULT = TDB_DEFAULT
+CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST
+INTERNAL = TDB_INTERNAL
+NOLOCK = TDB_NOLOCK
+NOMMAP = TDB_NOMMAP
+
+# Class representing a TDB file
+
+class Tdb:
+
+ # Create and destroy Tdb objects
+
+ def __init__(self, name, hash_size = 0, flags = TDB_DEFAULT,
+ open_flags = os.O_RDWR | os.O_CREAT, mode = 0600):
+ self.tdb = tdb_open(name, hash_size, flags, open_flags, mode)
+ if self.tdb is None:
+ raise IOError, tdb_errorstr(self.tdb)
+
+ def __del__(self):
+ self.close()
+
+ def close(self):
+ if hasattr(self, 'tdb') and self.tdb is not None:
+ if tdb_close(self.tdb) == -1:
+ raise IOError, tdb_errorstr(self.tdb)
+ self.tdb = None
+
+ # Random access to keys, values
+
+ def __getitem__(self, key):
+ result = tdb_fetch(self.tdb, key)
+ if result is None:
+ raise KeyError, '%s: %s' % (key, tdb_errorstr(self.tdb))
+ return result
+
+ def __setitem__(self, key, item):
+ if tdb_store(self.tdb, key, item) == -1:
+ raise IOError, tdb_errorstr(self.tdb)
+
+ def __delitem__(self, key):
+ if not tdb_exists(self.tdb, key):
+ raise KeyError, '%s: %s' % (key, tdb_errorstr(self.tdb))
+ tdb_delete(self.tdb, key)
+
+ def has_key(self, key):
+ return tdb_exists(self.tdb, key)
+
+ # Tdb iterator
+
+ class TdbIterator:
+ def __init__(self, tdb):
+ self.tdb = tdb
+ self.key = None
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if self.key is None:
+ self.key = tdb_firstkey(self.tdb)
+ if self.key is None:
+ raise StopIteration
+ return self.key
+ else:
+ self.key = tdb_nextkey(self.tdb, self.key)
+ if self.key is None:
+ raise StopIteration
+ return self.key
+
+ def __iter__(self):
+ return Tdb.TdbIterator(self.tdb)
+
+ # Implement other dict functions using TdbIterator
+
+ def keys(self):
+ return [k for k in iter(self)]
+
+ def values(self):
+ return [self[k] for k in iter(self)]
+
+ def items(self):
+ return [(k, self[k]) for k in iter(self)]
+
+ def __len__(self):
+ return len(self.keys())
+
+ def clear(self):
+ for k in iter(self):
+ del(self[k])
diff --git a/source/tdb/tdb.h b/source/tdb/swig/tdb.i
index b5b87ee5a54..98bf6441ce8 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/swig/tdb.i
@@ -1,13 +1,10 @@
-#ifndef __TDB_H__
-#define __TDB_H__
-
/*
Unix SMB/CIFS implementation.
-
- trivial database library
-
- Copyright (C) Andrew Tridgell 1999-2004
-
+
+ Swig interface to tdb.
+
+ Copyright (C) 2004,2005 Tim Potter <tpot@samba.org>
+
** NOTE! The following LGPL license applies to the tdb
** library. This does NOT imply that all of Samba is released
** under the LGPL
@@ -21,34 +18,83 @@
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef __cplusplus
-extern "C" {
+%module tdb
+
+%{
+
+/* This symbol is used in both includes.h and Python.h which causes an
+ annoying compiler warning. */
+
+#ifdef HAVE_FSTAT
+#undef HAVE_FSTAT
#endif
-#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
* properly **/
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#endif
-#endif
+
+/* Include tdb headers */
+
+#include "lib/tdb/include/tdb.h"
+
+%}
+
+/* The tdb functions will crash if a NULL tdb context is passed */
+
+%include exception.i
+
+%typemap(check) TDB_CONTEXT* {
+ if ($1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "tdb context must be non-NULL");
+}
+
+/* In and out typemaps for the TDB_DATA structure. This is converted to
+ and from the Python string type which can contain arbitrary binary
+ data.. */
+
+%typemap(in) TDB_DATA {
+ if (!PyString_Check($input)) {
+ PyErr_SetString(PyExc_TypeError, "string arg expected");
+ return NULL;
+ }
+ $1.dsize = PyString_Size($input);
+ $1.dptr = PyString_AsString($input);
+}
+
+%typemap(out) TDB_DATA {
+ if ($1.dptr == NULL && $1.dsize == 0) {
+ $result = Py_None;
+ } else {
+ $result = PyString_FromStringAndSize($1.dptr, $1.dsize);
+ free($1.dptr);
+ }
+}
+
+/* Treat a mode_t as an unsigned integer */
+
+typedef int mode_t;
/* flags to tdb_store() */
+
#define TDB_REPLACE 1
#define TDB_INSERT 2
#define TDB_MODIFY 3
/* flags for tdb_open() */
+
#define TDB_DEFAULT 0 /* just a readability place holder */
#define TDB_CLEAR_IF_FIRST 1
#define TDB_INTERNAL 2 /* don't store on disk */
@@ -57,106 +103,66 @@ extern "C" {
#define TDB_CONVERT 16 /* convert endian (internal use) */
#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
-#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
-
-/* error codes */
-enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
- TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
- TDB_ERR_NOEXIST};
+/* Throw an IOError exception if tdb_open() or tdb_open_ex() returns NULL */
-#ifndef u32
-#define u32 unsigned
-#endif
-
-typedef struct {
- char *dptr;
- size_t dsize;
-} TDB_DATA;
-
-typedef u32 tdb_len;
-typedef u32 tdb_off;
-
-/* this is stored at the front of every database */
-struct tdb_header {
- char magic_food[32]; /* for /etc/magic */
- u32 version; /* version of the code */
- u32 hash_size; /* number of hash entries */
- tdb_off rwlocks;
- tdb_off reserved[31];
-};
-
-struct tdb_lock_type {
- u32 count;
- u32 ltype;
-};
-
-struct tdb_traverse_lock {
- struct tdb_traverse_lock *next;
- u32 off;
- u32 hash;
-};
-
-/* this is the context structure that is returned from a db open */
-typedef struct tdb_context {
- char *name; /* the name of the database */
- void *map_ptr; /* where it is currently mapped */
- int fd; /* open file descriptor for the database */
- tdb_len map_size; /* how much space has been mapped */
- int read_only; /* opened read-only */
- struct tdb_lock_type *locked; /* array of chain locks */
- enum TDB_ERROR ecode; /* error code for last tdb error */
- struct tdb_header header; /* a cached copy of the header */
- u32 flags; /* the flags passed to tdb_open */
- struct tdb_traverse_lock travlocks; /* current traversal locks */
- struct tdb_context *next; /* all tdbs to avoid multiple opens */
- dev_t device; /* uniquely identifies this tdb */
- ino_t inode; /* uniquely identifies this tdb */
- void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
- u32 (*hash_fn)(TDB_DATA *key);
- int open_flags; /* flags used in the open - needed by reopen */
-} TDB_CONTEXT;
-
-typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
-typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
-typedef u32 (*tdb_hash_func)(TDB_DATA *key);
+%exception {
+ $action
+ if (result == NULL) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ SWIG_fail;
+ }
+}
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
+
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
tdb_log_func log_fn,
tdb_hash_func hash_fn);
+%exception;
+
int tdb_reopen(TDB_CONTEXT *tdb);
-int tdb_reopen_all(int);
+
+int tdb_reopen_all(int parent_longlived);
+
void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func);
+
enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
+
const char *tdb_errorstr(TDB_CONTEXT *tdb);
+
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
+
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+
+int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag = TDB_REPLACE);
+
int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
+
int tdb_close(TDB_CONTEXT *tdb);
+
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
+
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
+
+int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state);
+
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
+
int tdb_lockall(TDB_CONTEXT *tdb);
+
void tdb_unlockall(TDB_CONTEXT *tdb);
/* Low level locking functions: use with care */
-void tdb_set_lock_alarm(sig_atomic_t *palarm);
+
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
+
int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
/* Debug functions. Not used in production. */
-void tdb_dump_all(TDB_CONTEXT *tdb);
-int tdb_printfreelist(TDB_CONTEXT *tdb);
-extern TDB_DATA tdb_null;
-
-#ifdef __cplusplus
-}
-#endif
+void tdb_dump_all(TDB_CONTEXT *tdb);
-#endif /* tdb.h */
+int tdb_printfreelist(TDB_CONTEXT *tdb);
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
deleted file mode 100644
index ad73a1d9aa0..00000000000
--- a/source/tdb/tdb.c
+++ /dev/null
@@ -1,2127 +0,0 @@
- /*
- Unix SMB/CIFS implementation.
-
- trivial database library
-
- Copyright (C) Andrew Tridgell 1999-2004
- Copyright (C) Paul `Rusty' Russell 2000
- Copyright (C) Jeremy Allison 2000-2003
-
- ** NOTE! The following LGPL license applies to the tdb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-/* NOTE: If you use tdbs under valgrind, and in particular if you run
- * tdbtorture, you may get spurious "uninitialized value" warnings. I
- * think this is because valgrind doesn't understand that the mmap'd
- * area may be written to by other processes. Memory can, from the
- * point of view of the grinded process, spontaneously become
- * initialized.
- *
- * I can think of a few solutions. [mbp 20030311]
- *
- * 1 - Write suppressions for Valgrind so that it doesn't complain
- * about this. Probably the most reasonable but people need to
- * remember to use them.
- *
- * 2 - Use IO not mmap when running under valgrind. Not so nice.
- *
- * 3 - Use the special valgrind macros to mark memory as valid at the
- * right time. Probably too hard -- the process just doesn't know.
- */
-
-#ifdef STANDALONE
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include "tdb.h"
-#include "spinlock.h"
-#else
-#include "includes.h"
-
-#if defined(PARANOID_MALLOC_CHECKER)
-#ifdef malloc
-#undef malloc
-#endif
-
-#ifdef realloc
-#undef realloc
-#endif
-
-#ifdef calloc
-#undef calloc
-#endif
-
-#ifdef strdup
-#undef strdup
-#endif
-
-#ifdef strndup
-#undef strndup
-#endif
-
-#endif
-
-#endif
-
-#define TDB_MAGIC_FOOD "TDB file\n"
-#define TDB_VERSION (0x26011967 + 6)
-#define TDB_MAGIC (0x26011999U)
-#define TDB_FREE_MAGIC (~TDB_MAGIC)
-#define TDB_DEAD_MAGIC (0xFEE1DEAD)
-#define TDB_ALIGNMENT 4
-#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
-#define DEFAULT_HASH_SIZE 131
-#define TDB_PAGE_SIZE 0x2000
-#define FREELIST_TOP (sizeof(struct tdb_header))
-#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
-#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
-#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
-#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
-#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off))
-#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size))
-
-
-/* NB assumes there is a local variable called "tdb" that is the
- * current context, also takes doubly-parenthesized print-style
- * argument. */
-#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0)
-
-/* lock offsets */
-#define GLOBAL_LOCK 0
-#define ACTIVE_LOCK 4
-
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
-/* 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)
-#endif
-
-#define BUCKET(hash) ((hash) % tdb->header.hash_size)
-TDB_DATA tdb_null;
-
-/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
-static TDB_CONTEXT *tdbs = NULL;
-
-static int tdb_munmap(TDB_CONTEXT *tdb)
-{
- if (tdb->flags & TDB_INTERNAL)
- return 0;
-
-#ifdef HAVE_MMAP
- if (tdb->map_ptr) {
- int ret = munmap(tdb->map_ptr, tdb->map_size);
- if (ret != 0)
- return ret;
- }
-#endif
- tdb->map_ptr = NULL;
- return 0;
-}
-
-static void tdb_mmap(TDB_CONTEXT *tdb)
-{
- if (tdb->flags & TDB_INTERNAL)
- return;
-
-#ifdef HAVE_MMAP
- if (!(tdb->flags & TDB_NOMMAP)) {
- tdb->map_ptr = mmap(NULL, tdb->map_size,
- PROT_READ|(tdb->read_only? 0:PROT_WRITE),
- MAP_SHARED|MAP_FILE, tdb->fd, 0);
-
- /*
- * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
- */
-
- if (tdb->map_ptr == MAP_FAILED) {
- tdb->map_ptr = NULL;
- TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n",
- tdb->map_size, strerror(errno)));
- }
- } else {
- tdb->map_ptr = NULL;
- }
-#else
- tdb->map_ptr = NULL;
-#endif
-}
-
-/* Endian conversion: we only ever deal with 4 byte quantities */
-static void *convert(void *buf, u32 size)
-{
- u32 i, *p = buf;
- for (i = 0; i < size / 4; i++)
- p[i] = TDB_BYTEREV(p[i]);
- return buf;
-}
-#define DOCONV() (tdb->flags & TDB_CONVERT)
-#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x)
-
-/* the body of the database is made of one list_struct for the free space
- plus a separate data list for each hash value */
-struct list_struct {
- tdb_off next; /* offset of the next record in the list */
- tdb_len rec_len; /* total byte length of record */
- tdb_len key_len; /* byte length of key */
- tdb_len data_len; /* byte length of data */
- u32 full_hash; /* the full 32 bit hash of the key */
- u32 magic; /* try to catch errors */
- /* the following union is implied:
- union {
- char record[rec_len];
- struct {
- char key[key_len];
- char data[data_len];
- }
- u32 totalsize; (tailer)
- }
- */
-};
-
-/***************************************************************
- Allow a caller to set a "alarm" flag that tdb can check to abort
- a blocking lock on SIGALRM.
-***************************************************************/
-
-static sig_atomic_t *palarm_fired;
-
-void tdb_set_lock_alarm(sig_atomic_t *palarm)
-{
- palarm_fired = palarm;
-}
-
-/* a byte range locking function - return 0 on success
- this functions locks/unlocks 1 byte at the specified offset.
-
- On error, errno is also set so that errors are passed back properly
- through tdb_open(). */
-static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
- int rw_type, int lck_type, int probe)
-{
- struct flock fl;
- int ret;
-
- if (tdb->flags & TDB_NOLOCK)
- return 0;
- if ((rw_type == F_WRLCK) && (tdb->read_only)) {
- errno = EACCES;
- return -1;
- }
-
- fl.l_type = rw_type;
- fl.l_whence = SEEK_SET;
- fl.l_start = offset;
- fl.l_len = 1;
- fl.l_pid = 0;
-
- do {
- ret = fcntl(tdb->fd,lck_type,&fl);
- if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired)
- break;
- } while (ret == -1 && errno == EINTR);
-
- if (ret == -1) {
- if (!probe && lck_type != F_SETLK) {
- /* Ensure error code is set for log fun to examine. */
- if (errno == EINTR && palarm_fired && *palarm_fired)
- tdb->ecode = TDB_ERR_LOCK_TIMEOUT;
- else
- tdb->ecode = TDB_ERR_LOCK;
- TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n",
- tdb->fd, offset, rw_type, lck_type));
- }
- /* Was it an alarm timeout ? */
- if (errno == EINTR && palarm_fired && *palarm_fired) {
- TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n",
- tdb->fd, offset, rw_type, lck_type));
- return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
- }
- /* Otherwise - generic lock error. errno set by fcntl.
- * EAGAIN is an expected return from non-blocking
- * locks. */
- if (errno != EAGAIN) {
- TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n",
- tdb->fd, offset, rw_type, lck_type,
- strerror(errno)));
- }
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- }
- return 0;
-}
-
-/* lock a list in the database. list -1 is the alloc list */
-static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
-{
- if (list < -1 || list >= (int)tdb->header.hash_size) {
- TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n",
- list, ltype));
- return -1;
- }
- if (tdb->flags & TDB_NOLOCK)
- return 0;
-
- /* Since fcntl locks don't nest, we do a lock for the first one,
- and simply bump the count for future ones */
- if (tdb->locked[list+1].count == 0) {
- if (!tdb->read_only && tdb->header.rwlocks) {
- if (tdb_spinlock(tdb, list, ltype)) {
- TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n",
- list, ltype));
- return -1;
- }
- } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) {
- TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n",
- list, ltype, strerror(errno)));
- return -1;
- }
- tdb->locked[list+1].ltype = ltype;
- }
- tdb->locked[list+1].count++;
- return 0;
-}
-
-/* unlock the database: returns void because it's too late for errors. */
- /* changed to return int it may be interesting to know there
- has been an error --simo */
-static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype)
-{
- int ret = -1;
-
- if (tdb->flags & TDB_NOLOCK)
- return 0;
-
- /* Sanity checks */
- if (list < -1 || list >= (int)tdb->header.hash_size) {
- TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
- return ret;
- }
-
- if (tdb->locked[list+1].count==0) {
- TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n"));
- return ret;
- }
-
- if (tdb->locked[list+1].count == 1) {
- /* Down to last nested lock: unlock underneath */
- if (!tdb->read_only && tdb->header.rwlocks) {
- ret = tdb_spinunlock(tdb, list, ltype);
- } else {
- ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0);
- }
- } else {
- ret = 0;
- }
- tdb->locked[list+1].count--;
-
- if (ret)
- TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n"));
- return ret;
-}
-
-/* check for an out of bounds access - if it is out of bounds then
- see if the database has been expanded by someone else and expand
- if necessary
- note that "len" is the minimum length needed for the db
-*/
-static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe)
-{
- struct stat st;
- if (len <= tdb->map_size)
- return 0;
- if (tdb->flags & TDB_INTERNAL) {
- if (!probe) {
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_IO;
- TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n",
- (int)len, (int)tdb->map_size));
- }
- return TDB_ERRCODE(TDB_ERR_IO, -1);
- }
-
- if (fstat(tdb->fd, &st) == -1)
- return TDB_ERRCODE(TDB_ERR_IO, -1);
-
- if (st.st_size < (size_t)len) {
- if (!probe) {
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_IO;
- TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n",
- (int)len, (int)st.st_size));
- }
- return TDB_ERRCODE(TDB_ERR_IO, -1);
- }
-
- /* Unmap, update size, remap */
- if (tdb_munmap(tdb) == -1)
- return TDB_ERRCODE(TDB_ERR_IO, -1);
- tdb->map_size = st.st_size;
- tdb_mmap(tdb);
- return 0;
-}
-
-/* write a lump of data at a specified offset */
-static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len)
-{
- if (tdb_oob(tdb, off + len, 0) != 0)
- return -1;
-
- if (tdb->map_ptr)
- memcpy(off + (char *)tdb->map_ptr, buf, len);
-#ifdef HAVE_PWRITE
- else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
- else if (lseek(tdb->fd, off, SEEK_SET) != off
- || write(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_IO;
- TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n",
- off, len, strerror(errno)));
- return TDB_ERRCODE(TDB_ERR_IO, -1);
- }
- return 0;
-}
-
-/* read a lump of data at a specified offset, maybe convert */
-static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv)
-{
- if (tdb_oob(tdb, off + len, 0) != 0)
- return -1;
-
- if (tdb->map_ptr)
- memcpy(buf, off + (char *)tdb->map_ptr, len);
-#ifdef HAVE_PREAD
- else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
- else if (lseek(tdb->fd, off, SEEK_SET) != off
- || read(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_IO;
- TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n",
- off, len, strerror(errno)));
- return TDB_ERRCODE(TDB_ERR_IO, -1);
- }
- if (cv)
- convert(buf, len);
- return 0;
-}
-
-/* read a lump of data, allocating the space for it */
-static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len)
-{
- char *buf;
-
- if (!(buf = malloc(len))) {
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_OOM;
- TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n",
- len, strerror(errno)));
- return TDB_ERRCODE(TDB_ERR_OOM, buf);
- }
- if (tdb_read(tdb, offset, buf, len, 0) == -1) {
- SAFE_FREE(buf);
- return NULL;
- }
- return buf;
-}
-
-/* read/write a tdb_off */
-static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
- return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
-}
-static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
- tdb_off off = *d;
- return tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
-}
-
-/* read/write a record */
-static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
- if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
- return -1;
- if (TDB_BAD_MAGIC(rec)) {
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_CORRUPT;
- TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
- return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
- }
- return tdb_oob(tdb, rec->next+sizeof(*rec), 0);
-}
-static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
- struct list_struct r = *rec;
- return tdb_write(tdb, offset, CONVERT(r), sizeof(r));
-}
-
-/* read a freelist record and check for simple errors */
-static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec)
-{
- if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
- return -1;
-
- if (rec->magic == TDB_MAGIC) {
- /* this happens when a app is showdown while deleting a record - we should
- not completely fail when this happens */
- TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
- rec->magic, off));
- rec->magic = TDB_FREE_MAGIC;
- if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
- return -1;
- }
-
- if (rec->magic != TDB_FREE_MAGIC) {
- /* Ensure ecode is set for log fn. */
- tdb->ecode = TDB_ERR_CORRUPT;
- TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n",
- rec->magic, off));
- return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
- }
- if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
- return -1;
- return 0;
-}
-
-/* update a record tailer (must hold allocation lock) */
-static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset,
- const struct list_struct *rec)
-{
- tdb_off totalsize;
-
- /* Offset of tailer from record header */
- totalsize = sizeof(*rec) + rec->rec_len;
- return ofs_write(tdb, offset + totalsize - sizeof(tdb_off),
- &totalsize);
-}
-
-static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset)
-{
- struct list_struct rec;
- tdb_off tailer_ofs, tailer;
-
- if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
- printf("ERROR: failed to read record at %u\n", offset);
- return 0;
- }
-
- printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
- offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic);
-
- tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off);
- if (ofs_read(tdb, tailer_ofs, &tailer) == -1) {
- printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
- return rec.next;
- }
-
- if (tailer != rec.rec_len + sizeof(rec)) {
- printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
- (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec)));
- }
- return rec.next;
-}
-
-static int tdb_dump_chain(TDB_CONTEXT *tdb, int i)
-{
- tdb_off rec_ptr, top;
- int hash_length = 0;
-
- top = TDB_HASH_TOP(i);
-
- if (tdb_lock(tdb, i, F_WRLCK) != 0)
- return -1;
-
- if (ofs_read(tdb, top, &rec_ptr) == -1)
- return tdb_unlock(tdb, i, F_WRLCK);
-
- if (rec_ptr)
- printf("hash=%d\n", i);
-
- while (rec_ptr) {
- rec_ptr = tdb_dump_record(tdb, rec_ptr);
- hash_length += 1;
- }
-
- printf("chain %d length %d\n", i, hash_length);
-
- return tdb_unlock(tdb, i, F_WRLCK);
-}
-
-void tdb_dump_all(TDB_CONTEXT *tdb)
-{
- int i;
- for (i=0;i<tdb->header.hash_size;i++) {
- tdb_dump_chain(tdb, i);
- }
- tdb_printfreelist(tdb);
-}
-
-int tdb_printfreelist(TDB_CONTEXT *tdb)
-{
- int ret;
- long total_free = 0;
- tdb_off offset, rec_ptr;
- struct list_struct rec;
-
- if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
- return ret;
-
- offset = FREELIST_TOP;
-
- /* read in the freelist top */
- if (ofs_read(tdb, offset, &rec_ptr) == -1) {
- tdb_unlock(tdb, -1, F_WRLCK);
- return 0;
- }
-
- printf("freelist top=[0x%08x]\n", rec_ptr );
- while (rec_ptr) {
- if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
- tdb_unlock(tdb, -1, F_WRLCK);
- return -1;
- }
-
- if (rec.magic != TDB_FREE_MAGIC) {
- printf("bad magic 0x%08x in free list\n", rec.magic);
- tdb_unlock(tdb, -1, F_WRLCK);
- return -1;
- }
-
- printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len );
- total_free += rec.rec_len;
-
- /* move to the next record */
- rec_ptr = rec.next;
- }
- printf("total rec_len = [0x%08x (%d)]\n", (int)total_free,
- (int)total_free);
-
- return tdb_unlock(tdb, -1, F_WRLCK);
-}
-
-/* Remove an element from the freelist. Must have alloc lock. */
-static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next)
-{
- tdb_off last_ptr, i;
-
- /* read in the freelist top */
- last_ptr = FREELIST_TOP;
- while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
- if (i == off) {
- /* We've found it! */
- return ofs_write(tdb, last_ptr, &next);
- }
- /* Follow chain (next offset is at start of record) */
- last_ptr = i;
- }
- TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off));
- return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-}
-
-/* Add an element into the freelist. Merge adjacent records if
- neccessary. */
-static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
- tdb_off right, left;
-
- /* Allocation and tailer lock */
- if (tdb_lock(tdb, -1, F_WRLCK) != 0)
- return -1;
-
- /* set an initial tailer, so if we fail we don't leave a bogus record */
- if (update_tailer(tdb, offset, rec) != 0) {
- TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n"));
- goto fail;
- }
-
- /* Look right first (I'm an Australian, dammit) */
- right = offset + sizeof(*rec) + rec->rec_len;
- if (right + sizeof(*rec) <= tdb->map_size) {
- struct list_struct r;
-
- if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right));
- goto left;
- }
-
- /* If it's free, expand to include it. */
- if (r.magic == TDB_FREE_MAGIC) {
- if (remove_from_freelist(tdb, right, r.next) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right));
- goto left;
- }
- rec->rec_len += sizeof(r) + r.rec_len;
- }
- }
-
-left:
- /* Look left */
- left = offset - sizeof(tdb_off);
- if (left > TDB_DATA_START(tdb->header.hash_size)) {
- struct list_struct l;
- tdb_off leftsize;
-
- /* Read in tailer and jump back to header */
- if (ofs_read(tdb, left, &leftsize) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
- goto update;
- }
- left = offset - leftsize;
-
- /* Now read in record */
- if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
- goto update;
- }
-
- /* If it's free, expand to include it. */
- if (l.magic == TDB_FREE_MAGIC) {
- if (remove_from_freelist(tdb, left, l.next) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left));
- goto update;
- } else {
- offset = left;
- rec->rec_len += leftsize;
- }
- }
- }
-
-update:
- if (update_tailer(tdb, offset, rec) == -1) {
- TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset));
- goto fail;
- }
-
- /* Now, prepend to free list */
- rec->magic = TDB_FREE_MAGIC;
-
- if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
- rec_write(tdb, offset, rec) == -1 ||
- ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
- TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset));
- goto fail;
- }
-
- /* And we're done. */
- tdb_unlock(tdb, -1, F_WRLCK);
- return 0;
-
- fail:
- tdb_unlock(tdb, -1, F_WRLCK);
- return -1;
-}
-
-
-/* expand a file. we prefer to use ftruncate, as that is what posix
- says to use for mmap expansion */
-static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition)
-{
- char buf[1024];
-#if HAVE_FTRUNCATE_EXTEND
- if (ftruncate(tdb->fd, size+addition) != 0) {
- TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n",
- size+addition, strerror(errno)));
- return -1;
- }
-#else
- char b = 0;
-
-#ifdef HAVE_PWRITE
- if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) {
-#else
- if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 ||
- write(tdb->fd, &b, 1) != 1) {
-#endif
- TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n",
- size+addition, strerror(errno)));
- return -1;
- }
-#endif
-
- /* now fill the file with something. This ensures that the file isn't sparse, which would be
- very bad if we ran out of disk. This must be done with write, not via mmap */
- memset(buf, 0x42, sizeof(buf));
- while (addition) {
- int n = addition>sizeof(buf)?sizeof(buf):addition;
-#ifdef HAVE_PWRITE
- int ret = pwrite(tdb->fd, buf, n, size);
-#else
- int ret;
- if (lseek(tdb->fd, size, SEEK_SET) != size)
- return -1;
- ret = write(tdb->fd, buf, n);
-#endif
- if (ret != n) {
- TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n",
- n, strerror(errno)));
- return -1;
- }
- addition -= n;
- size += n;
- }
- return 0;
-}
-
-
-/* expand the database at least size bytes by expanding the underlying
- file and doing the mmap again if necessary */
-static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size)
-{
- struct list_struct rec;
- tdb_off offset;
-
- if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
- TDB_LOG((tdb, 0, "lock failed in tdb_expand\n"));
- return -1;
- }
-
- /* must know about any previous expansions by another process */
- tdb_oob(tdb, tdb->map_size + 1, 1);
-
- /* always make room for at least 10 more records, and round
- the database up to a multiple of TDB_PAGE_SIZE */
- size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size;
-
- if (!(tdb->flags & TDB_INTERNAL))
- tdb_munmap(tdb);
-
- /*
- * We must ensure the file is unmapped before doing this
- * to ensure consistency with systems like OpenBSD where
- * writes and mmaps are not consistent.
- */
-
- /* expand the file itself */
- if (!(tdb->flags & TDB_INTERNAL)) {
- if (expand_file(tdb, tdb->map_size, size) != 0)
- goto fail;
- }
-
- tdb->map_size += size;
-
- if (tdb->flags & TDB_INTERNAL) {
- char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size);
- if (!new_map_ptr) {
- tdb->map_size -= size;
- goto fail;
- }
- tdb->map_ptr = new_map_ptr;
- } else {
- /*
- * We must ensure the file is remapped before adding the space
- * to ensure consistency with systems like OpenBSD where
- * writes and mmaps are not consistent.
- */
-
- /* We're ok if the mmap fails as we'll fallback to read/write */
- tdb_mmap(tdb);
- }
-
- /* form a new freelist record */
- memset(&rec,'\0',sizeof(rec));
- rec.rec_len = size - sizeof(rec);
-
- /* link it into the free list */
- offset = tdb->map_size - size;
- if (tdb_free(tdb, offset, &rec) == -1)
- goto fail;
-
- tdb_unlock(tdb, -1, F_WRLCK);
- return 0;
- fail:
- tdb_unlock(tdb, -1, F_WRLCK);
- return -1;
-}
-
-/* allocate some space from the free list. The offset returned points
- to a unconnected list_struct within the database with room for at
- least length bytes of total data
-
- 0 is returned if the space could not be allocated
- */
-static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
- struct list_struct *rec)
-{
- tdb_off rec_ptr, last_ptr, newrec_ptr;
- struct list_struct newrec;
-
- memset(&newrec, '\0', sizeof(newrec));
-
- if (tdb_lock(tdb, -1, F_WRLCK) == -1)
- return 0;
-
- /* Extra bytes required for tailer */
- length += sizeof(tdb_off);
-
- again:
- last_ptr = FREELIST_TOP;
-
- /* read in the freelist top */
- if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
- goto fail;
-
- /* keep looking until we find a freelist record big enough */
- while (rec_ptr) {
- if (rec_free_read(tdb, rec_ptr, rec) == -1)
- goto fail;
-
- if (rec->rec_len >= length) {
- /* found it - now possibly split it up */
- if (rec->rec_len > length + MIN_REC_SIZE) {
- /* Length of left piece */
- length = TDB_ALIGN(length, TDB_ALIGNMENT);
-
- /* Right piece to go on free list */
- newrec.rec_len = rec->rec_len
- - (sizeof(*rec) + length);
- newrec_ptr = rec_ptr + sizeof(*rec) + length;
-
- /* And left record is shortened */
- rec->rec_len = length;
- } else
- newrec_ptr = 0;
-
- /* Remove allocated record from the free list */
- if (ofs_write(tdb, last_ptr, &rec->next) == -1)
- goto fail;
-
- /* Update header: do this before we drop alloc
- lock, otherwise tdb_free() might try to
- merge with us, thinking we're free.
- (Thanks Jeremy Allison). */
- rec->magic = TDB_MAGIC;
- if (rec_write(tdb, rec_ptr, rec) == -1)
- goto fail;
-
- /* Did we create new block? */
- if (newrec_ptr) {
- /* Update allocated record tailer (we
- shortened it). */
- if (update_tailer(tdb, rec_ptr, rec) == -1)
- goto fail;
-
- /* Free new record */
- if (tdb_free(tdb, newrec_ptr, &newrec) == -1)
- goto fail;
- }
-
- /* all done - return the new record offset */
- tdb_unlock(tdb, -1, F_WRLCK);
- return rec_ptr;
- }
- /* move to the next record */
- last_ptr = rec_ptr;
- rec_ptr = rec->next;
- }
- /* we didn't find enough space. See if we can expand the
- database and if we can then try again */
- if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
- goto again;
- fail:
- tdb_unlock(tdb, -1, F_WRLCK);
- return 0;
-}
-
-/* initialise a new database with a specified hash size */
-static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
-{
- struct tdb_header *newdb;
- int size, ret = -1;
-
- /* We make it up in memory, then write it out if not internal */
- size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off);
- if (!(newdb = calloc(size, 1)))
- return TDB_ERRCODE(TDB_ERR_OOM, -1);
-
- /* Fill in the header */
- newdb->version = TDB_VERSION;
- newdb->hash_size = hash_size;
-#ifdef USE_SPINLOCKS
- newdb->rwlocks = size;
-#endif
- if (tdb->flags & TDB_INTERNAL) {
- tdb->map_size = size;
- tdb->map_ptr = (char *)newdb;
- memcpy(&tdb->header, newdb, sizeof(tdb->header));
- /* Convert the `ondisk' version if asked. */
- CONVERT(*newdb);
- return 0;
- }
- if (lseek(tdb->fd, 0, SEEK_SET) == -1)
- goto fail;
-
- if (ftruncate(tdb->fd, 0) == -1)
- goto fail;
-
- /* This creates an endian-converted header, as if read from disk */
- CONVERT(*newdb);
- memcpy(&tdb->header, newdb, sizeof(tdb->header));
- /* Don't endian-convert the magic food! */
- memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
- if (write(tdb->fd, newdb, size) != size)
- ret = -1;
- else
- ret = tdb_create_rwlocks(tdb->fd, hash_size);
-
- fail:
- SAFE_FREE(newdb);
- return ret;
-}
-
-/* Returns 0 on fail. On success, return offset of record, and fills
- in rec */
-static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
- struct list_struct *r)
-{
- tdb_off rec_ptr;
-
- /* read in the hash top */
- if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
- return 0;
-
- /* keep looking until we find the right record */
- while (rec_ptr) {
- if (rec_read(tdb, rec_ptr, r) == -1)
- return 0;
-
- if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) {
- char *k;
- /* a very likely hit - read the key */
- k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r),
- r->key_len);
- if (!k)
- return 0;
-
- if (memcmp(key.dptr, k, key.dsize) == 0) {
- SAFE_FREE(k);
- return rec_ptr;
- }
- SAFE_FREE(k);
- }
- rec_ptr = r->next;
- }
- return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
-}
-
-/* As tdb_find, but if you succeed, keep the lock */
-static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
- struct list_struct *rec)
-{
- u32 rec_ptr;
-
- if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
- return 0;
- if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
- tdb_unlock(tdb, BUCKET(hash), locktype);
- return rec_ptr;
-}
-
-enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb)
-{
- return tdb->ecode;
-}
-
-static struct tdb_errname {
- enum TDB_ERROR ecode; const char *estring;
-} emap[] = { {TDB_SUCCESS, "Success"},
- {TDB_ERR_CORRUPT, "Corrupt database"},
- {TDB_ERR_IO, "IO Error"},
- {TDB_ERR_LOCK, "Locking error"},
- {TDB_ERR_OOM, "Out of memory"},
- {TDB_ERR_EXISTS, "Record exists"},
- {TDB_ERR_NOLOCK, "Lock exists on other keys"},
- {TDB_ERR_NOEXIST, "Record does not exist"} };
-
-/* Error string for the last tdb error */
-const char *tdb_errorstr(TDB_CONTEXT *tdb)
-{
- u32 i;
- for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++)
- if (tdb->ecode == emap[i].ecode)
- return emap[i].estring;
- return "Invalid error code";
-}
-
-/* update an entry in place - this only works if the new data size
- is <= the old data size and the key exists.
- on failure return -1.
-*/
-
-static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
-{
- struct list_struct rec;
- tdb_off rec_ptr;
-
- /* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
- return -1;
-
- /* must be long enough key, data and tailer */
- if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) {
- tdb->ecode = TDB_SUCCESS; /* Not really an error */
- return -1;
- }
-
- if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
- dbuf.dptr, dbuf.dsize) == -1)
- return -1;
-
- if (dbuf.dsize != rec.data_len) {
- /* update size */
- rec.data_len = dbuf.dsize;
- return rec_write(tdb, rec_ptr, &rec);
- }
-
- return 0;
-}
-
-/* find an entry in the database given a key */
-/* If an entry doesn't exist tdb_err will be set to
- * TDB_ERR_NOEXIST. If a key has no data attached
- * tdb_err will not be set. Both will return a
- * zero pptr and zero dsize.
- */
-
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- tdb_off rec_ptr;
- struct list_struct rec;
- TDB_DATA ret;
- u32 hash;
-
- /* find which hash bucket it is in */
- hash = tdb->hash_fn(&key);
- if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
- return tdb_null;
-
- if (rec.data_len)
- ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
- rec.data_len);
- else
- ret.dptr = NULL;
- ret.dsize = rec.data_len;
- tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
- return ret;
-}
-
-/* check if an entry in the database exists
-
- note that 1 is returned if the key is found and 0 is returned if not found
- this doesn't match the conventions in the rest of this module, but is
- compatible with gdbm
-*/
-static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
-{
- struct list_struct rec;
-
- if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
- return 0;
- tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
- return 1;
-}
-
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- u32 hash = tdb->hash_fn(&key);
- return tdb_exists_hash(tdb, key, hash);
-}
-
-/* record lock stops delete underneath */
-static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
- return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0;
-}
-/*
- Write locks override our own fcntl readlocks, so check it here.
- Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
- an error to fail to get the lock here.
-*/
-
-static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
- struct tdb_traverse_lock *i;
- for (i = &tdb->travlocks; i; i = i->next)
- if (i->off == off)
- return -1;
- return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1);
-}
-
-/*
- Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
- an error to fail to get the lock here.
-*/
-
-static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
- return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0);
-}
-/* fcntl locks don't stack: avoid unlocking someone else's */
-static int unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
- struct tdb_traverse_lock *i;
- u32 count = 0;
-
- if (off == 0)
- return 0;
- for (i = &tdb->travlocks; i; i = i->next)
- if (i->off == off)
- count++;
- return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0);
-}
-
-/* actually delete an entry in the database given the offset */
-static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec)
-{
- tdb_off last_ptr, i;
- struct list_struct lastrec;
-
- if (tdb->read_only) return -1;
-
- if (write_lock_record(tdb, rec_ptr) == -1) {
- /* Someone traversing here: mark it as dead */
- rec->magic = TDB_DEAD_MAGIC;
- return rec_write(tdb, rec_ptr, rec);
- }
- if (write_unlock_record(tdb, rec_ptr) != 0)
- return -1;
-
- /* find previous record in hash chain */
- if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
- return -1;
- for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next)
- if (rec_read(tdb, i, &lastrec) == -1)
- return -1;
-
- /* unlink it: next ptr is at start of record. */
- if (last_ptr == 0)
- last_ptr = TDB_HASH_TOP(rec->full_hash);
- if (ofs_write(tdb, last_ptr, &rec->next) == -1)
- return -1;
-
- /* recover the space */
- if (tdb_free(tdb, rec_ptr, rec) == -1)
- return -1;
- return 0;
-}
-
-/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */
-static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
- struct list_struct *rec)
-{
- int want_next = (tlock->off != 0);
-
- /* Lock each chain from the start one. */
- for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
-
- /* this is an optimisation for the common case where
- the hash chain is empty, which is particularly
- common for the use of tdb with ldb, where large
- hashes are used. In that case we spend most of our
- time in tdb_brlock(), locking empty hash chains.
-
- To avoid this, we do an unlocked pre-check to see
- if the hash chain is empty before starting to look
- inside it. If it is empty then we can avoid that
- hash chain. If it isn't empty then we can't believe
- the value we get back, as we read it without a
- lock, so instead we get the lock and re-fetch the
- value below.
-
- Notice that not doing this optimisation on the
- first hash chain is critical. We must guarantee
- that we have done at least one fcntl lock at the
- start of a search to guarantee that memory is
- coherent on SMP systems. If records are added by
- others during the search then thats OK, and we
- could possibly miss those with this trick, but we
- could miss them anyway without this trick, so the
- semantics don't change.
-
- With a non-indexed ldb search this trick gains us a
- factor of around 80 in speed on a linux 2.6.x
- system (testing using ldbtest).
- */
- if (!tlock->off && tlock->hash != 0) {
- u32 off;
- if (tdb->map_ptr) {
- for (;tlock->hash < tdb->header.hash_size;tlock->hash++) {
- if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) {
- break;
- }
- }
- if (tlock->hash == tdb->header.hash_size) {
- continue;
- }
- } else {
- if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 &&
- off == 0) {
- continue;
- }
- }
- }
-
- if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1)
- return -1;
-
- /* No previous record? Start at top of chain. */
- if (!tlock->off) {
- if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
- &tlock->off) == -1)
- goto fail;
- } else {
- /* Otherwise unlock the previous record. */
- if (unlock_record(tdb, tlock->off) != 0)
- goto fail;
- }
-
- if (want_next) {
- /* We have offset of old record: grab next */
- if (rec_read(tdb, tlock->off, rec) == -1)
- goto fail;
- tlock->off = rec->next;
- }
-
- /* Iterate through chain */
- while( tlock->off) {
- tdb_off current;
- if (rec_read(tdb, tlock->off, rec) == -1)
- goto fail;
-
- /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
- if (tlock->off == rec->next) {
- TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n"));
- goto fail;
- }
-
- if (!TDB_DEAD(rec)) {
- /* Woohoo: we found one! */
- if (lock_record(tdb, tlock->off) != 0)
- goto fail;
- return tlock->off;
- }
-
- /* Try to clean dead ones from old traverses */
- current = tlock->off;
- tlock->off = rec->next;
- if (!tdb->read_only &&
- do_delete(tdb, current, rec) != 0)
- goto fail;
- }
- tdb_unlock(tdb, tlock->hash, F_WRLCK);
- want_next = 0;
- }
- /* We finished iteration without finding anything */
- return TDB_ERRCODE(TDB_SUCCESS, 0);
-
- fail:
- tlock->off = 0;
- if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0)
- TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n"));
- return -1;
-}
-
-/* traverse the entire database - calling fn(tdb, key, data) on each element.
- return -1 on error or the record count traversed
- if fn is NULL then it is not called
- a non-zero return value from fn() indicates that the traversal should stop
- */
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val)
-{
- TDB_DATA key, dbuf;
- struct list_struct rec;
- struct tdb_traverse_lock tl = { NULL, 0, 0 };
- int ret, count = 0;
-
- /* This was in the initializaton, above, but the IRIX compiler
- * did not like it. crh
- */
- tl.next = tdb->travlocks.next;
-
- /* fcntl locks don't stack: beware traverse inside traverse */
- tdb->travlocks.next = &tl;
-
- /* tdb_next_lock places locks on the record returned, and its chain */
- while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) {
- count++;
- /* now read the full record */
- key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec),
- rec.key_len + rec.data_len);
- if (!key.dptr) {
- ret = -1;
- if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0)
- goto out;
- if (unlock_record(tdb, tl.off) != 0)
- TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
- goto out;
- }
- key.dsize = rec.key_len;
- dbuf.dptr = key.dptr + rec.key_len;
- dbuf.dsize = rec.data_len;
-
- /* Drop chain lock, call out */
- if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) {
- ret = -1;
- SAFE_FREE(key.dptr);
- goto out;
- }
- if (fn && fn(tdb, key, dbuf, private_val)) {
- /* They want us to terminate traversal */
- ret = count;
- if (unlock_record(tdb, tl.off) != 0) {
- TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));;
- ret = -1;
- }
- SAFE_FREE(key.dptr);
- goto out;
- }
- SAFE_FREE(key.dptr);
- }
-out:
- tdb->travlocks.next = tl.next;
- if (ret < 0)
- return -1;
- else
- return count;
-}
-
-/* find the first entry in the database and return its key */
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb)
-{
- TDB_DATA key;
- struct list_struct rec;
-
- /* release any old lock */
- if (unlock_record(tdb, tdb->travlocks.off) != 0)
- return tdb_null;
- tdb->travlocks.off = tdb->travlocks.hash = 0;
-
- if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
- return tdb_null;
- /* now read the key */
- key.dsize = rec.key_len;
- key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
- if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
- TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
- return key;
-}
-
-/* find the next entry in the database, returning its key */
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
-{
- u32 oldhash;
- TDB_DATA key = tdb_null;
- struct list_struct rec;
- char *k = NULL;
-
- /* Is locked key the old key? If so, traverse will be reliable. */
- if (tdb->travlocks.off) {
- if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
- return tdb_null;
- if (rec_read(tdb, tdb->travlocks.off, &rec) == -1
- || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
- rec.key_len))
- || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
- /* No, it wasn't: unlock it and start from scratch */
- if (unlock_record(tdb, tdb->travlocks.off) != 0) {
- SAFE_FREE(k);
- return tdb_null;
- }
- if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
- SAFE_FREE(k);
- return tdb_null;
- }
- tdb->travlocks.off = 0;
- }
-
- SAFE_FREE(k);
- }
-
- if (!tdb->travlocks.off) {
- /* No previous element: do normal find, and lock record */
- tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
- if (!tdb->travlocks.off)
- return tdb_null;
- tdb->travlocks.hash = BUCKET(rec.full_hash);
- if (lock_record(tdb, tdb->travlocks.off) != 0) {
- TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
- return tdb_null;
- }
- }
- oldhash = tdb->travlocks.hash;
-
- /* Grab next record: locks chain and returned record,
- unlocks old record */
- if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
- key.dsize = rec.key_len;
- key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
- key.dsize);
- /* Unlock the chain of this new record */
- if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
- TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
- }
- /* Unlock the chain of old record */
- if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
- TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
- return key;
-}
-
-/* delete an entry in the database given a key */
-static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
-{
- tdb_off rec_ptr;
- struct list_struct rec;
- int ret;
-
- if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
- return -1;
- ret = do_delete(tdb, rec_ptr, &rec);
- if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
- TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n"));
- return ret;
-}
-
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- u32 hash = tdb->hash_fn(&key);
- return tdb_delete_hash(tdb, key, hash);
-}
-
-/* store an element in the database, replacing any existing element
- with the same key
-
- return 0 on success, -1 on failure
-*/
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
-{
- struct list_struct rec;
- u32 hash;
- tdb_off rec_ptr;
- char *p = NULL;
- int ret = 0;
-
- /* find which hash bucket it is in */
- hash = tdb->hash_fn(&key);
- if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
- return -1;
-
- /* check for it existing, on insert. */
- if (flag == TDB_INSERT) {
- if (tdb_exists_hash(tdb, key, hash)) {
- tdb->ecode = TDB_ERR_EXISTS;
- goto fail;
- }
- } else {
- /* first try in-place update, on modify or replace. */
- if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
- goto out;
- if (tdb->ecode == TDB_ERR_NOEXIST &&
- flag == TDB_MODIFY) {
- /* if the record doesn't exist and we are in TDB_MODIFY mode then
- we should fail the store */
- goto fail;
- }
- }
- /* reset the error code potentially set by the tdb_update() */
- tdb->ecode = TDB_SUCCESS;
-
- /* delete any existing record - if it doesn't exist we don't
- care. Doing this first reduces fragmentation, and avoids
- coalescing with `allocated' block before it's updated. */
- if (flag != TDB_INSERT)
- tdb_delete_hash(tdb, key, hash);
-
- /* Copy key+value *before* allocating free space in case malloc
- fails and we are left with a dead spot in the tdb. */
-
- if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
- tdb->ecode = TDB_ERR_OOM;
- goto fail;
- }
-
- memcpy(p, key.dptr, key.dsize);
- if (dbuf.dsize)
- memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
-
- /* we have to allocate some space */
- if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
- goto fail;
-
- /* Read hash top into next ptr */
- if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
- goto fail;
-
- rec.key_len = key.dsize;
- rec.data_len = dbuf.dsize;
- rec.full_hash = hash;
- rec.magic = TDB_MAGIC;
-
- /* write out and point the top of the hash chain at it */
- if (rec_write(tdb, rec_ptr, &rec) == -1
- || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
- || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
- /* Need to tdb_unallocate() here */
- goto fail;
- }
- out:
- SAFE_FREE(p);
- tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
- return ret;
-fail:
- ret = -1;
- goto out;
-}
-
-/* Attempt to append data to an entry in place - this only works if the new data size
- is <= the old data size and the key exists.
- on failure return -1. Record must be locked before calling.
-*/
-static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
-{
- struct list_struct rec;
- tdb_off rec_ptr;
-
- /* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
- return -1;
-
- /* Append of 0 is always ok. */
- if (new_dbuf.dsize == 0)
- return 0;
-
- /* must be long enough for key, old data + new data and tailer */
- if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) {
- /* No room. */
- tdb->ecode = TDB_SUCCESS; /* Not really an error */
- return -1;
- }
-
- if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len,
- new_dbuf.dptr, new_dbuf.dsize) == -1)
- return -1;
-
- /* update size */
- rec.data_len += new_dbuf.dsize;
- return rec_write(tdb, rec_ptr, &rec);
-}
-
-/* Append to an entry. Create if not exist. */
-
-int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
-{
- struct list_struct rec;
- u32 hash;
- tdb_off rec_ptr;
- char *p = NULL;
- int ret = 0;
- size_t new_data_size = 0;
-
- /* find which hash bucket it is in */
- hash = tdb->hash_fn(&key);
- if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
- return -1;
-
- /* first try in-place. */
- if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
- goto out;
-
- /* reset the error code potentially set by the tdb_append_inplace() */
- tdb->ecode = TDB_SUCCESS;
-
- /* find entry */
- if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
- if (tdb->ecode != TDB_ERR_NOEXIST)
- goto fail;
-
- /* Not found - create. */
-
- ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT);
- goto out;
- }
-
- new_data_size = rec.data_len + new_dbuf.dsize;
-
- /* Copy key+old_value+value *before* allocating free space in case malloc
- fails and we are left with a dead spot in the tdb. */
-
- if (!(p = (char *)malloc(key.dsize + new_data_size))) {
- tdb->ecode = TDB_ERR_OOM;
- goto fail;
- }
-
- /* Copy the key in place. */
- memcpy(p, key.dptr, key.dsize);
-
- /* Now read the old data into place. */
- if (rec.data_len &&
- tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1)
- goto fail;
-
- /* Finally append the new data. */
- if (new_dbuf.dsize)
- memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize);
-
- /* delete any existing record - if it doesn't exist we don't
- care. Doing this first reduces fragmentation, and avoids
- coalescing with `allocated' block before it's updated. */
-
- tdb_delete_hash(tdb, key, hash);
-
- if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
- goto fail;
-
- /* Read hash top into next ptr */
- if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
- goto fail;
-
- rec.key_len = key.dsize;
- rec.data_len = new_data_size;
- rec.full_hash = hash;
- rec.magic = TDB_MAGIC;
-
- /* write out and point the top of the hash chain at it */
- if (rec_write(tdb, rec_ptr, &rec) == -1
- || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1
- || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
- /* Need to tdb_unallocate() here */
- goto fail;
- }
-
- out:
- SAFE_FREE(p);
- tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
- return ret;
-
-fail:
- ret = -1;
- goto out;
-}
-
-static int tdb_already_open(dev_t device,
- ino_t ino)
-{
- TDB_CONTEXT *i;
-
- for (i = tdbs; i; i = i->next) {
- if (i->device == device && i->inode == ino) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/* This is based on the hash algorithm from gdbm */
-static u32 default_tdb_hash(TDB_DATA *key)
-{
- u32 value; /* Used to compute the hash value. */
- u32 i; /* Used to cycle through random values. */
-
- /* Set the initial value from the key size. */
- for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
- value = (value + (key->dptr[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345);
-}
-
-/* open the database, creating it if necessary
-
- The open_flags and mode are passed straight to the open call on the
- database file. A flags value of O_WRONLY is invalid. The hash size
- is advisory, use zero for a default value.
-
- Return is NULL on error, in which case errno is also set. Don't
- try to call tdb_error or tdb_errname, just do strerror(errno).
-
- @param name may be NULL for internal databases. */
-TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
- int open_flags, mode_t mode)
-{
- return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
-}
-
-
-TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
- int open_flags, mode_t mode,
- tdb_log_func log_fn,
- tdb_hash_func hash_fn)
-{
- TDB_CONTEXT *tdb;
- struct stat st;
- int rev = 0, locked = 0;
- unsigned char *vp;
- u32 vertest;
-
- if (!(tdb = calloc(1, sizeof *tdb))) {
- /* Can't log this */
- errno = ENOMEM;
- goto fail;
- }
- tdb->fd = -1;
- tdb->name = NULL;
- tdb->map_ptr = NULL;
- tdb->flags = tdb_flags;
- tdb->open_flags = open_flags;
- tdb->log_fn = log_fn;
- tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
-
- if ((open_flags & O_ACCMODE) == O_WRONLY) {
- TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
- name));
- errno = EINVAL;
- goto fail;
- }
-
- if (hash_size == 0)
- hash_size = DEFAULT_HASH_SIZE;
- if ((open_flags & O_ACCMODE) == O_RDONLY) {
- tdb->read_only = 1;
- /* read only databases don't do locking or clear if first */
- tdb->flags |= TDB_NOLOCK;
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
- }
-
- /* internal databases don't mmap or lock, and start off cleared */
- if (tdb->flags & TDB_INTERNAL) {
- tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
- if (tdb_new_database(tdb, hash_size) != 0) {
- TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!"));
- goto fail;
- }
- goto internal;
- }
-
- if ((tdb->fd = open(name, open_flags, mode)) == -1) {
- TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n",
- name, strerror(errno)));
- goto fail; /* errno set by open(2) */
- }
-
- /* ensure there is only one process initialising at once */
- if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) {
- TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n",
- name, strerror(errno)));
- goto fail; /* errno set by tdb_brlock */
- }
-
- /* we need to zero database if we are the only one with it open */
- if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
- (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
- open_flags |= O_CREAT;
- if (ftruncate(tdb->fd, 0) == -1) {
- TDB_LOG((tdb, 0, "tdb_open_ex: "
- "failed to truncate %s: %s\n",
- name, strerror(errno)));
- goto fail; /* errno set by ftruncate */
- }
- }
-
- if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
- || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
- || (tdb->header.version != TDB_VERSION
- && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
- /* its not a valid database - possibly initialise it */
- if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
- errno = EIO; /* ie bad format or something */
- goto fail;
- }
- rev = (tdb->flags & TDB_CONVERT);
- }
- vp = (unsigned char *)&tdb->header.version;
- vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
- (((u32)vp[2]) << 8) | (u32)vp[3];
- tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
- if (!rev)
- tdb->flags &= ~TDB_CONVERT;
- else {
- tdb->flags |= TDB_CONVERT;
- convert(&tdb->header, sizeof(tdb->header));
- }
- if (fstat(tdb->fd, &st) == -1)
- goto fail;
-
- /* Is it already in the open list? If so, fail. */
- if (tdb_already_open(st.st_dev, st.st_ino)) {
- TDB_LOG((tdb, 2, "tdb_open_ex: "
- "%s (%d,%d) is already open in this process\n",
- name, (int)st.st_dev, (int)st.st_ino));
- errno = EBUSY;
- goto fail;
- }
-
- if (!(tdb->name = (char *)strdup(name))) {
- errno = ENOMEM;
- goto fail;
- }
-
- tdb->map_size = st.st_size;
- tdb->device = st.st_dev;
- tdb->inode = st.st_ino;
- tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0]));
- if (!tdb->locked) {
- TDB_LOG((tdb, 2, "tdb_open_ex: "
- "failed to allocate lock structure for %s\n",
- name));
- errno = ENOMEM;
- goto fail;
- }
- tdb_mmap(tdb);
- if (locked) {
- if (!tdb->read_only)
- if (tdb_clear_spinlocks(tdb) != 0) {
- TDB_LOG((tdb, 0, "tdb_open_ex: "
- "failed to clear spinlock\n"));
- goto fail;
- }
- if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) {
- TDB_LOG((tdb, 0, "tdb_open_ex: "
- "failed to take ACTIVE_LOCK on %s: %s\n",
- name, strerror(errno)));
- goto fail;
- }
-
- }
-
- /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
- we didn't get the initial exclusive lock as we need to let all other
- users know we're using it. */
-
- if (tdb_flags & TDB_CLEAR_IF_FIRST) {
- /* leave this lock in place to indicate it's in use */
- if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
- goto fail;
- }
-
-
- internal:
- /* Internal (memory-only) databases skip all the code above to
- * do with disk files, and resume here by releasing their
- * global lock and hooking into the active list. */
- if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
- goto fail;
- tdb->next = tdbs;
- tdbs = tdb;
- return tdb;
-
- fail:
- { int save_errno = errno;
-
- if (!tdb)
- return NULL;
-
- if (tdb->map_ptr) {
- if (tdb->flags & TDB_INTERNAL)
- SAFE_FREE(tdb->map_ptr);
- else
- tdb_munmap(tdb);
- }
- SAFE_FREE(tdb->name);
- if (tdb->fd != -1)
- if (close(tdb->fd) != 0)
- TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n"));
- SAFE_FREE(tdb->locked);
- SAFE_FREE(tdb);
- errno = save_errno;
- return NULL;
- }
-}
-
-/**
- * Close a database.
- *
- * @returns -1 for error; 0 for success.
- **/
-int tdb_close(TDB_CONTEXT *tdb)
-{
- TDB_CONTEXT **i;
- int ret = 0;
-
- if (tdb->map_ptr) {
- if (tdb->flags & TDB_INTERNAL)
- SAFE_FREE(tdb->map_ptr);
- else
- tdb_munmap(tdb);
- }
- SAFE_FREE(tdb->name);
- if (tdb->fd != -1)
- ret = close(tdb->fd);
- SAFE_FREE(tdb->locked);
-
- /* Remove from contexts list */
- for (i = &tdbs; *i; i = &(*i)->next) {
- if (*i == tdb) {
- *i = tdb->next;
- break;
- }
- }
-
- memset(tdb, 0, sizeof(*tdb));
- SAFE_FREE(tdb);
-
- return ret;
-}
-
-/* lock/unlock entire database */
-int tdb_lockall(TDB_CONTEXT *tdb)
-{
- u32 i;
-
- /* There are no locks on read-only dbs */
- if (tdb->read_only)
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- for (i = 0; i < tdb->header.hash_size; i++)
- if (tdb_lock(tdb, i, F_WRLCK))
- break;
-
- /* If error, release locks we have... */
- if (i < tdb->header.hash_size) {
- u32 j;
-
- for ( j = 0; j < i; j++)
- tdb_unlock(tdb, j, F_WRLCK);
- return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
- }
-
- return 0;
-}
-void tdb_unlockall(TDB_CONTEXT *tdb)
-{
- u32 i;
- for (i=0; i < tdb->header.hash_size; i++)
- tdb_unlock(tdb, i, F_WRLCK);
-}
-
-/* lock/unlock one hash chain. This is meant to be used to reduce
- contention - it cannot guarantee how many records will be locked */
-int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-}
-
-int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-}
-
-int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
-}
-
-int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
-{
- return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
-}
-
-
-/* register a loging function */
-void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...))
-{
- tdb->log_fn = fn;
-}
-
-/* reopen a tdb - this can be used after a fork to ensure that we have an independent
- seek pointer from our parent and to re-establish locks */
-int tdb_reopen(TDB_CONTEXT *tdb)
-{
- struct stat st;
-
- if (tdb->flags & TDB_INTERNAL)
- return 0; /* Nothing to do. */
- if (tdb_munmap(tdb) != 0) {
- TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
- goto fail;
- }
- if (close(tdb->fd) != 0)
- TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
- tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
- if (tdb->fd == -1) {
- TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno)));
- goto fail;
- }
- if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
- (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
- TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
- goto fail;
- }
- if (fstat(tdb->fd, &st) != 0) {
- TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
- goto fail;
- }
- if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
- TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n"));
- goto fail;
- }
- tdb_mmap(tdb);
-
- return 0;
-
-fail:
- tdb_close(tdb);
- return -1;
-}
-
-/* reopen all tdb's */
-int tdb_reopen_all(int parent_longlived)
-{
- TDB_CONTEXT *tdb;
-
- for (tdb=tdbs; tdb; tdb = tdb->next) {
- /*
- * If the parent is longlived (ie. a
- * parent daemon architecture), we know
- * it will keep it's active lock on a
- * tdb opened with CLEAR_IF_FIRST. Thus
- * for child processes we don't have to
- * add an active lock. This is essential
- * to improve performance on systems that
- * keep POSIX locks as a non-scalable data
- * structure in the kernel.
- */
- if (parent_longlived) {
- /* Ensure no clear-if-first. */
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
- }
-
- if (tdb_reopen(tdb) != 0)
- return -1;
- }
-
- return 0;
-}
diff --git a/source/tdb/tdb.pc.in b/source/tdb/tdb.pc.in
new file mode 100644
index 00000000000..0d54afe2424
--- /dev/null
+++ b/source/tdb/tdb.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: tdb
+Description: A trivial database
+Version: 4.0
+#Libs: @LIBS@ -L${libdir} -ltdb
+Cflags: -I${includedir} @CFLAGS@
diff --git a/source/tdb/tdbtorture.c b/source/tdb/tdbtorture.c
deleted file mode 100644
index 2d367b91e1f..00000000000
--- a/source/tdb/tdbtorture.c
+++ /dev/null
@@ -1,227 +0,0 @@
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include "tdb.h"
-
-/* this tests tdb by doing lots of ops from several simultaneous
- writers - that stresses the locking code. Build with TDB_DEBUG=1
- for best effect */
-
-
-
-#define REOPEN_PROB 30
-#define DELETE_PROB 8
-#define STORE_PROB 4
-#define APPEND_PROB 6
-#define LOCKSTORE_PROB 0
-#define TRAVERSE_PROB 20
-#define CULL_PROB 100
-#define KEYLEN 3
-#define DATALEN 100
-#define LOCKLEN 20
-
-static TDB_CONTEXT *db;
-
-static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vfprintf(stdout, format, ap);
- va_end(ap);
- fflush(stdout);
-#if 0
- {
- char *ptr;
- asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
- system(ptr);
- free(ptr);
- }
-#endif
-}
-
-static void fatal(char *why)
-{
- perror(why);
- exit(1);
-}
-
-static char *randbuf(int len)
-{
- char *buf;
- int i;
- buf = (char *)malloc(len+1);
-
- for (i=0;i<len;i++) {
- buf[i] = 'a' + (rand() % 26);
- }
- buf[i] = 0;
- return buf;
-}
-
-static int cull_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
- void *state)
-{
- if (random() % CULL_PROB == 0) {
- tdb_delete(tdb, key);
- }
- return 0;
-}
-
-static void addrec_db(void)
-{
- int klen, dlen, slen;
- char *k, *d, *s;
- TDB_DATA key, data, lockkey;
-
- klen = 1 + (rand() % KEYLEN);
- dlen = 1 + (rand() % DATALEN);
- slen = 1 + (rand() % LOCKLEN);
-
- k = randbuf(klen);
- d = randbuf(dlen);
- s = randbuf(slen);
-
- key.dptr = k;
- key.dsize = klen+1;
-
- data.dptr = d;
- data.dsize = dlen+1;
-
- lockkey.dptr = s;
- lockkey.dsize = slen+1;
-
-#if REOPEN_PROB
- if (random() % REOPEN_PROB == 0) {
- tdb_reopen_all(1);
- goto next;
- }
-#endif
-
-#if DELETE_PROB
- if (random() % DELETE_PROB == 0) {
- tdb_delete(db, key);
- goto next;
- }
-#endif
-
-#if STORE_PROB
- if (random() % STORE_PROB == 0) {
- if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
- fatal("tdb_store failed");
- }
- goto next;
- }
-#endif
-
-#if APPEND_PROB
- if (random() % APPEND_PROB == 0) {
- if (tdb_append(db, key, data) != 0) {
- fatal("tdb_append failed");
- }
- goto next;
- }
-#endif
-
-#if LOCKSTORE_PROB
- if (random() % LOCKSTORE_PROB == 0) {
- tdb_chainlock(db, lockkey);
- data = tdb_fetch(db, key);
- if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
- fatal("tdb_store failed");
- }
- if (data.dptr) free(data.dptr);
- tdb_chainunlock(db, lockkey);
- goto next;
- }
-#endif
-
-#if TRAVERSE_PROB
- if (random() % TRAVERSE_PROB == 0) {
- tdb_traverse(db, cull_traverse, NULL);
- goto next;
- }
-#endif
-
- data = tdb_fetch(db, key);
- if (data.dptr) free(data.dptr);
-
-next:
- free(k);
- free(d);
- free(s);
-}
-
-static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
- void *state)
-{
- tdb_delete(tdb, key);
- return 0;
-}
-
-#ifndef NPROC
-#define NPROC 6
-#endif
-
-#ifndef NLOOPS
-#define NLOOPS 200000
-#endif
-
-int main(int argc, char *argv[])
-{
- int i, seed=0;
- int loops = NLOOPS;
- pid_t pids[NPROC];
-
- db = tdb_open("torture.tdb", 0, TDB_CLEAR_IF_FIRST,
- O_RDWR | O_CREAT, 0600);
- if (!db) {
- fatal("db open failed");
- }
-
- for (i=0;i<NPROC;i++) {
- pids[i] = fork();
- if (pids[i] == 0) {
- tdb_reopen_all(1);
-
- tdb_logging_function(db, tdb_log);
-
- srand(seed + getpid());
- srandom(seed + getpid() + time(NULL));
- for (i=0;i<loops;i++) addrec_db();
-
- tdb_traverse(db, NULL, NULL);
- tdb_traverse(db, traverse_fn, NULL);
- tdb_traverse(db, traverse_fn, NULL);
-
- tdb_close(db);
- exit(0);
- }
- }
-
- for (i=0;i<NPROC;i++) {
- int status;
- if (waitpid(pids[i], &status, 0) != pids[i]) {
- printf("failed to wait for %d\n",
- (int)pids[i]);
- exit(1);
- }
- if (WEXITSTATUS(status) != 0) {
- printf("child %d exited with status %d\n",
- (int)pids[i], WEXITSTATUS(status));
- exit(1);
- }
- }
- printf("OK\n");
- return 0;
-}
diff --git a/source/tdb/tdbbackup.c b/source/tdb/tools/tdbbackup.c
index f49cd339c79..4ae5a4f9212 100644
--- a/source/tdb/tdbbackup.c
+++ b/source/tdb/tools/tdbbackup.c
@@ -93,6 +93,7 @@ static void usage(void)
printf(" -h this help message\n");
printf(" -s suffix set the backup suffix\n");
printf(" -v verify mode (restore if corrupt)\n");
+ printf(" -n hashsize set the new hash size for the backup\n");
}
@@ -102,9 +103,10 @@ static void usage(void)
int ret = 0;
int c;
int verify = 0;
+ int hashsize = 0;
const char *suffix = ".bak";
- while ((c = getopt(argc, argv, "vhs:")) != -1) {
+ while ((c = getopt(argc, argv, "vhs:n:")) != -1) {
switch (c) {
case 'h':
usage();
@@ -115,6 +117,9 @@ static void usage(void)
case 's':
suffix = optarg;
break;
+ case 'n':
+ hashsize = atoi(optarg);
+ break;
}
}
@@ -138,7 +143,7 @@ static void usage(void)
}
} else {
if (file_newer(fname, bak_name) &&
- backup_tdb(fname, bak_name) != 0) {
+ backup_tdb(fname, bak_name, hashsize) != 0) {
ret = 1;
}
}
diff --git a/source/tdb/tdbdump.c b/source/tdb/tools/tdbdump.c
index b702fb07355..b702fb07355 100644
--- a/source/tdb/tdbdump.c
+++ b/source/tdb/tools/tdbdump.c
diff --git a/source/tdb/tdbtest.c b/source/tdb/tools/tdbtest.c
index 89295a3291f..1564a42bc41 100644
--- a/source/tdb/tdbtest.c
+++ b/source/tdb/tools/tdbtest.c
@@ -1,48 +1,43 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <signal.h>
-#include "tdb.h"
-#include <gdbm.h>
-
/* a test program for tdb - the trivial database */
+#include "replace.h"
+#include "tdb.h"
+#include "system/filesys.h"
+#include "system/time.h"
+
+#include <gdbm.h>
#define DELETE_PROB 7
#define STORE_PROB 5
-static TDB_CONTEXT *db;
+static struct tdb_context *db;
static GDBM_FILE gdbm;
struct timeval tp1,tp2;
-static void start_timer(void)
+static void _start_timer(void)
{
gettimeofday(&tp1,NULL);
}
-static double end_timer(void)
+static double _end_timer(void)
{
gettimeofday(&tp2,NULL);
return((tp2.tv_sec - tp1.tv_sec) +
(tp2.tv_usec - tp1.tv_usec)*1.0e-6);
}
-static void fatal(char *why)
+static void fatal(const char *why)
{
perror(why);
exit(1);
}
-static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
+#ifdef PRINTF_ATTRIBUTE
+static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+#endif
+static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...)
{
va_list ap;
@@ -179,7 +174,7 @@ static void addrec_gdbm(void)
free(d);
}
-static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
+static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
{
#if 0
printf("[%s] [%s]\n", key.dptr, dbuf.dptr);
@@ -192,14 +187,15 @@ static void merge_test(void)
{
int i;
char keys[5][2];
+ char tdata[] = "test";
TDB_DATA key, data;
for (i = 0; i < 5; i++) {
- sprintf(keys[i], "%d", i);
+ snprintf(keys[i],2, "%d", i);
key.dptr = keys[i];
key.dsize = 2;
- data.dptr = "test";
+ data.dptr = tdata;
data.dsize = 4;
if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
@@ -219,37 +215,43 @@ static void merge_test(void)
tdb_delete(db, key);
}
-int main(int argc, char *argv[])
+ int main(int argc, const char *argv[])
{
int i, seed=0;
int loops = 10000;
+ int num_entries;
+ char test_gdbm[] = "test.gdbm";
unlink("test.gdbm");
db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT | O_TRUNC, 0600);
- gdbm = gdbm_open("test.gdbm", 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
+ gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
0600, NULL);
if (!db || !gdbm) {
fatal("db open failed");
}
- tdb_logging_function(db, tdb_log);
-
#if 1
srand(seed);
- start_timer();
+ _start_timer();
for (i=0;i<loops;i++) addrec_gdbm();
- printf("gdbm got %.2f ops/sec\n", i/end_timer());
+ printf("gdbm got %.2f ops/sec\n", i/_end_timer());
#endif
merge_test();
srand(seed);
- start_timer();
+ _start_timer();
for (i=0;i<loops;i++) addrec_db();
- printf("tdb got %.2f ops/sec\n", i/end_timer());
+ printf("tdb got %.2f ops/sec\n", i/_end_timer());
+
+ if (tdb_validate_freelist(db, &num_entries) == -1) {
+ printf("tdb freelist is corrupt\n");
+ } else {
+ printf("tdb freelist is good (%d entries)\n", num_entries);
+ }
compare_db();
diff --git a/source/tdb/tdbtool.c b/source/tdb/tools/tdbtool.c
index bcfb96adc09..bcfb96adc09 100644
--- a/source/tdb/tdbtool.c
+++ b/source/tdb/tools/tdbtool.c
diff --git a/source/tdb/tools/tdbtorture.c b/source/tdb/tools/tdbtorture.c
new file mode 100644
index 00000000000..14a2b48cdc7
--- /dev/null
+++ b/source/tdb/tools/tdbtorture.c
@@ -0,0 +1,318 @@
+/* this tests tdb by doing lots of ops from several simultaneous
+ writers - that stresses the locking code.
+*/
+
+#include "replace.h"
+#include "tdb.h"
+#include "system/time.h"
+#include "system/wait.h"
+#include "system/filesys.h"
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+
+#define REOPEN_PROB 30
+#define DELETE_PROB 8
+#define STORE_PROB 4
+#define APPEND_PROB 6
+#define TRANSACTION_PROB 10
+#define LOCKSTORE_PROB 5
+#define TRAVERSE_PROB 20
+#define TRAVERSE_READ_PROB 20
+#define CULL_PROB 100
+#define KEYLEN 3
+#define DATALEN 100
+
+static struct tdb_context *db;
+static int in_transaction;
+static int error_count;
+
+#ifdef PRINTF_ATTRIBUTE
+static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+#endif
+static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...)
+{
+ va_list ap;
+
+ error_count++;
+
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+ fflush(stdout);
+#if 0
+ {
+ char *ptr;
+ asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
+ system(ptr);
+ free(ptr);
+ }
+#endif
+}
+
+static void fatal(const char *why)
+{
+ perror(why);
+ error_count++;
+}
+
+static char *randbuf(int len)
+{
+ char *buf;
+ int i;
+ buf = (char *)malloc(len+1);
+
+ for (i=0;i<len;i++) {
+ buf[i] = 'a' + (rand() % 26);
+ }
+ buf[i] = 0;
+ return buf;
+}
+
+static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+#if CULL_PROB
+ if (random() % CULL_PROB == 0) {
+ tdb_delete(tdb, key);
+ }
+#endif
+ return 0;
+}
+
+static void addrec_db(void)
+{
+ int klen, dlen;
+ char *k, *d;
+ TDB_DATA key, data;
+
+ klen = 1 + (rand() % KEYLEN);
+ dlen = 1 + (rand() % DATALEN);
+
+ k = randbuf(klen);
+ d = randbuf(dlen);
+
+ key.dptr = (unsigned char *)k;
+ key.dsize = klen+1;
+
+ data.dptr = (unsigned char *)d;
+ data.dsize = dlen+1;
+
+#if TRANSACTION_PROB
+ if (in_transaction == 0 && random() % TRANSACTION_PROB == 0) {
+ if (tdb_transaction_start(db) != 0) {
+ fatal("tdb_transaction_start failed");
+ }
+ in_transaction++;
+ goto next;
+ }
+ if (in_transaction && random() % TRANSACTION_PROB == 0) {
+ if (tdb_transaction_commit(db) != 0) {
+ fatal("tdb_transaction_commit failed");
+ }
+ in_transaction--;
+ goto next;
+ }
+ if (in_transaction && random() % TRANSACTION_PROB == 0) {
+ if (tdb_transaction_cancel(db) != 0) {
+ fatal("tdb_transaction_cancel failed");
+ }
+ in_transaction--;
+ goto next;
+ }
+#endif
+
+#if REOPEN_PROB
+ if (in_transaction == 0 && random() % REOPEN_PROB == 0) {
+ tdb_reopen_all(0);
+ goto next;
+ }
+#endif
+
+#if DELETE_PROB
+ if (random() % DELETE_PROB == 0) {
+ tdb_delete(db, key);
+ goto next;
+ }
+#endif
+
+#if STORE_PROB
+ if (random() % STORE_PROB == 0) {
+ if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
+ fatal("tdb_store failed");
+ }
+ goto next;
+ }
+#endif
+
+#if APPEND_PROB
+ if (random() % APPEND_PROB == 0) {
+ if (tdb_append(db, key, data) != 0) {
+ fatal("tdb_append failed");
+ }
+ goto next;
+ }
+#endif
+
+#if LOCKSTORE_PROB
+ if (random() % LOCKSTORE_PROB == 0) {
+ tdb_chainlock(db, key);
+ data = tdb_fetch(db, key);
+ if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
+ fatal("tdb_store failed");
+ }
+ if (data.dptr) free(data.dptr);
+ tdb_chainunlock(db, key);
+ goto next;
+ }
+#endif
+
+#if TRAVERSE_PROB
+ if (random() % TRAVERSE_PROB == 0) {
+ tdb_traverse(db, cull_traverse, NULL);
+ goto next;
+ }
+#endif
+
+#if TRAVERSE_READ_PROB
+ if (random() % TRAVERSE_READ_PROB == 0) {
+ tdb_traverse_read(db, NULL, NULL);
+ goto next;
+ }
+#endif
+
+ data = tdb_fetch(db, key);
+ if (data.dptr) free(data.dptr);
+
+next:
+ free(k);
+ free(d);
+}
+
+static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+ tdb_delete(tdb, key);
+ return 0;
+}
+
+static void usage(void)
+{
+ printf("Usage: tdbtorture [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
+ exit(0);
+}
+
+ int main(int argc, char * const *argv)
+{
+ int i, seed = -1;
+ int num_procs = 3;
+ int num_loops = 5000;
+ int hash_size = 2;
+ int c;
+ extern char *optarg;
+ pid_t *pids;
+
+ struct tdb_logging_context log_ctx;
+ log_ctx.log_fn = tdb_log;
+
+ while ((c = getopt(argc, argv, "n:l:s:H:h")) != -1) {
+ switch (c) {
+ case 'n':
+ num_procs = strtol(optarg, NULL, 0);
+ break;
+ case 'l':
+ num_loops = strtol(optarg, NULL, 0);
+ break;
+ case 'H':
+ hash_size = strtol(optarg, NULL, 0);
+ break;
+ case 's':
+ seed = strtol(optarg, NULL, 0);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ unlink("torture.tdb");
+
+ pids = calloc(sizeof(pid_t), num_procs);
+ pids[0] = getpid();
+
+ for (i=0;i<num_procs-1;i++) {
+ if ((pids[i+1]=fork()) == 0) break;
+ }
+
+ db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST,
+ O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
+ if (!db) {
+ fatal("db open failed");
+ }
+
+ if (seed == -1) {
+ seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
+ }
+
+ if (i == 0) {
+ printf("testing with %d processes, %d loops, %d hash_size, seed=%d\n",
+ num_procs, num_loops, hash_size, seed);
+ }
+
+ srand(seed + i);
+ srandom(seed + i);
+
+ for (i=0;i<num_loops && error_count == 0;i++) {
+ addrec_db();
+ }
+
+ if (error_count == 0) {
+ tdb_traverse_read(db, NULL, NULL);
+ tdb_traverse(db, traverse_fn, NULL);
+ tdb_traverse(db, traverse_fn, NULL);
+ }
+
+ tdb_close(db);
+
+ if (getpid() != pids[0]) {
+ return error_count;
+ }
+
+ for (i=1;i<num_procs;i++) {
+ int status, j;
+ pid_t pid;
+ if (error_count != 0) {
+ /* try and stop the test on any failure */
+ for (j=1;j<num_procs;j++) {
+ if (pids[j] != 0) {
+ kill(pids[j], SIGTERM);
+ }
+ }
+ }
+ pid = waitpid(-1, &status, 0);
+ if (pid == -1) {
+ perror("failed to wait for child\n");
+ exit(1);
+ }
+ for (j=1;j<num_procs;j++) {
+ if (pids[j] == pid) break;
+ }
+ if (j == num_procs) {
+ printf("unknown child %d exited!?\n", (int)pid);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) != 0) {
+ printf("child %d exited with status %d\n",
+ (int)pid, WEXITSTATUS(status));
+ error_count++;
+ }
+ pids[j] = 0;
+ }
+
+ if (error_count == 0) {
+ printf("OK\n");
+ }
+
+ return error_count;
+}
diff --git a/source/torture/cmd_vfs.c b/source/torture/cmd_vfs.c
index cc683977e8c..6cecd693f83 100644
--- a/source/torture/cmd_vfs.c
+++ b/source/torture/cmd_vfs.c
@@ -94,7 +94,7 @@ static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar
static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
- SMB_VFS_CONNECT(vfs->conn, lp_servicename(vfs->conn->service), "vfstest");
+ SMB_VFS_CONNECT(vfs->conn, lp_servicename(SNUM(vfs->conn)), "vfstest");
return NT_STATUS_OK;
}
@@ -200,9 +200,10 @@ static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg
static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
- int flags, fd;
+ int flags;
mode_t mode;
const char *flagstr;
+ files_struct *fsp;
mode = 00400;
@@ -278,18 +279,21 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
}
}
- fd = SMB_VFS_OPEN(vfs->conn, argv[1], flags, mode);
- if (fd == -1) {
+ fsp = SMB_MALLOC_P(struct files_struct);
+ fsp->fsp_name = SMB_STRDUP(argv[1]);
+ fsp->fh = SMB_MALLOC_P(struct fd_handle);
+ fsp->conn = vfs->conn;
+
+ fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, argv[1], fsp, flags, mode);
+ if (fsp->fh->fd == -1) {
printf("open: error=%d (%s)\n", errno, strerror(errno));
+ SAFE_FREE(fsp->fh);
+ SAFE_FREE(fsp);
return NT_STATUS_UNSUCCESSFUL;
}
- vfs->files[fd] = SMB_MALLOC_P(struct files_struct);
- vfs->files[fd]->fsp_name = SMB_STRDUP(argv[1]);
- vfs->files[fd]->fh = SMB_MALLOC_P(struct fd_handle);
- vfs->files[fd]->fh->fd = fd;
- vfs->files[fd]->conn = vfs->conn;
- printf("open: fd=%d\n", fd);
+ vfs->files[fsp->fh->fd] = fsp;
+ printf("open: fd=%d\n", fsp->fh->fd);
return NT_STATUS_OK;
}
diff --git a/source/torture/denytest.c b/source/torture/denytest.c
index 291a4035af7..2dc5c2b634f 100644
--- a/source/torture/denytest.c
+++ b/source/torture/denytest.c
@@ -1412,7 +1412,7 @@ BOOL torture_denytest1(int dummy)
BOOL correct = True;
const char *fnames[2] = {"\\denytest1.dat", "\\denytest1.exe"};
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -1447,10 +1447,10 @@ BOOL torture_denytest1(int dummy)
} else {
char x = 1;
res = A_0;
- if (cli_read(cli1, fnum2, (void *)&x, 0, 1) == 1) {
+ if (cli_read(cli1, fnum2, (char *)&x, 0, 1) == 1) {
res += A_R;
}
- if (cli_write(cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
+ if (cli_write(cli1, fnum2, 0, (char *)&x, 0, 1) == 1) {
res += A_W;
}
}
@@ -1498,7 +1498,7 @@ BOOL torture_denytest2(int dummy)
BOOL correct = True;
const char *fnames[2] = {"\\denytest2.dat", "\\denytest2.exe"};
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
@@ -1531,10 +1531,10 @@ BOOL torture_denytest2(int dummy)
} else {
char x = 1;
res = A_0;
- if (cli_read(cli2, fnum2, (void *)&x, 0, 1) == 1) {
+ if (cli_read(cli2, fnum2, (char *)&x, 0, 1) == 1) {
res += A_R;
}
- if (cli_write(cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
+ if (cli_write(cli2, fnum2, 0, (char *)&x, 0, 1) == 1) {
res += A_W;
}
}
diff --git a/source/torture/locktest.c b/source/torture/locktest.c
index b946e48666e..d248a9459db 100644
--- a/source/torture/locktest.c
+++ b/source/torture/locktest.c
@@ -36,6 +36,9 @@ static unsigned min_length = 0;
static BOOL exact_error_codes;
static BOOL zero_zero;
+extern char *optarg;
+extern int optind;
+
#define FILENAME "\\locktest.dat"
#define READ_PCT 50
@@ -51,14 +54,14 @@ static BOOL zero_zero;
enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};
-const char *lock_op_type(int op)
+static const char *lock_op_type(int op)
{
if (op == WRITE_LOCK) return "write";
else if (op == READ_LOCK) return "read";
else return "other";
}
-const char *lock_op_name(enum lock_op op)
+static const char *lock_op_name(enum lock_op op)
{
if (op == OP_LOCK) return "lock";
else if (op == OP_UNLOCK) return "unlock";
@@ -113,9 +116,13 @@ static struct record preset[] = {
static struct record *recorded;
-static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid,
- enum brl_type lock_type,
- br_off start, br_off size)
+static void print_brl(SMB_DEV_T dev,
+ SMB_INO_T ino,
+ struct process_id pid,
+ enum brl_type lock_type,
+ enum brl_flavour lock_flav,
+ br_off start,
+ br_off size)
{
#if NASTY_POSIX_LOCK_HACK
{
@@ -178,7 +185,7 @@ static struct cli_state *connect_one(char *share, int snum)
zero_ip(&ip);
/* have to open a new connection */
- if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) {
+ if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) {
DEBUG(0,("Connection to %s failed\n", server_n));
return NULL;
}
@@ -216,10 +223,12 @@ static struct cli_state *connect_one(char *share, int snum)
fstrcpy(username[1], username[0]);
}
- if (!cli_session_setup(c, username[snum],
- password[snum], strlen(password[snum]),
- password[snum], strlen(password[snum]),
- lp_workgroup())) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(c, username[snum],
+ password[snum],
+ strlen(password[snum]),
+ password[snum],
+ strlen(password[snum]),
+ lp_workgroup()))) {
DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
return NULL;
}
@@ -575,8 +584,6 @@ static void usage(void)
int main(int argc,char *argv[])
{
char *share[NSERVERS];
- extern char *optarg;
- extern int optind;
int opt;
char *p;
int seed, server;
diff --git a/source/torture/locktest2.c b/source/torture/locktest2.c
index 519acebe8e8..0a897fb2065 100644
--- a/source/torture/locktest2.c
+++ b/source/torture/locktest2.c
@@ -29,6 +29,9 @@ static BOOL analyze;
static BOOL hide_unlock_fails;
static BOOL use_oplocks;
+extern char *optarg;
+extern int optind;
+
#define FILENAME "\\locktest.dat"
#define LOCKRANGE 100
#define LOCKBASE 0
@@ -135,6 +138,7 @@ static BOOL try_unlock(struct cli_state *c, int fstype,
static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid,
enum brl_type lock_type,
+ enum brl_flavour lock_flav,
br_off start, br_off size)
{
printf("%6d %05x:%05x %s %.0f:%.0f(%.0f)\n",
@@ -470,8 +474,6 @@ static void usage(void)
int main(int argc,char *argv[])
{
char *share1, *share2, *nfspath1, *nfspath2;
- extern char *optarg;
- extern int optind;
int opt;
char *p;
int seed;
diff --git a/source/torture/mangle_test.c b/source/torture/mangle_test.c
index 9ce6afa038f..1c9fba355a6 100644
--- a/source/torture/mangle_test.c
+++ b/source/torture/mangle_test.c
@@ -167,7 +167,7 @@ BOOL torture_mangle(int dummy)
printf("starting mangle test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
diff --git a/source/torture/masktest.c b/source/torture/masktest.c
index ffc9a20e71c..0d6c0b16f28 100644
--- a/source/torture/masktest.c
+++ b/source/torture/masktest.c
@@ -33,8 +33,12 @@ static int die_on_error;
static int NumLoops = 0;
static int ignore_dot_errors = 0;
+extern char *optarg;
+extern int optind;
+extern BOOL AllowDebugChange;
+
/* a test fn for LANMAN mask support */
-int ms_fnmatch_lanman_core(const char *pattern, const char *string)
+static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
{
const char *p = pattern, *n = string;
char c;
@@ -108,7 +112,7 @@ next:
return 0;
}
-int ms_fnmatch_lanman(const char *pattern, const char *string)
+static int ms_fnmatch_lanman(const char *pattern, const char *string)
{
if (!strpbrk(pattern, "?*<>\"")) {
if (strcmp(string,"..") == 0)
@@ -159,7 +163,7 @@ static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, cha
/*****************************************************
return a connection to a server
*******************************************************/
-struct cli_state *connect_one(char *share)
+static struct cli_state *connect_one(char *share)
{
struct cli_state *c;
struct nmb_name called, calling;
@@ -184,7 +188,7 @@ struct cli_state *connect_one(char *share)
zero_ip(&ip);
/* have to open a new connection */
- if (!(c=cli_initialise(NULL)) || !cli_connect(c, server_n, &ip)) {
+ if (!(c=cli_initialise()) || !cli_connect(c, server_n, &ip)) {
DEBUG(0,("Connection to %s failed\n", server_n));
return NULL;
}
@@ -216,10 +220,10 @@ struct cli_state *connect_one(char *share)
}
}
- if (!cli_session_setup(c, username,
- password, strlen(password),
- password, strlen(password),
- lp_workgroup())) {
+ if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
+ password, strlen(password),
+ password, strlen(password),
+ lp_workgroup()))) {
DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
return NULL;
}
@@ -426,9 +430,6 @@ static void usage(void)
{
char *share;
struct cli_state *cli;
- extern char *optarg;
- extern int optind;
- extern BOOL AllowDebugChange;
int opt;
char *p;
int seed;
diff --git a/source/torture/msgtest.c b/source/torture/msgtest.c
index 035214b3a96..5a066bc599e 100644
--- a/source/torture/msgtest.c
+++ b/source/torture/msgtest.c
@@ -26,27 +26,11 @@
static int pong_count;
-/* samba4 timeval functions */
-
-double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
-{
- return (tv2->tv_sec - tv1->tv_sec) +
- (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
-}
-
-/**
- return the number of seconds elapsed since a given time
-*/
-double timeval_elapsed(const struct timeval *tv)
-{
- struct timeval tv2 = timeval_current();
- return timeval_elapsed2(tv, &tv2);
-}
-
/****************************************************************************
a useful function for testing the message system
****************************************************************************/
-void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
+static void pong_message(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
pong_count++;
}
@@ -66,14 +50,15 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
message_init();
if (argc != 3) {
- fprintf(stderr, "%s: Usage - %s pid count\n", argv[0], argv[0]);
+ fprintf(stderr, "%s: Usage - %s pid count\n", argv[0],
+ argv[0]);
exit(1);
}
pid = atoi(argv[1]);
n = atoi(argv[2]);
- message_register(MSG_PONG, pong_message);
+ message_register(MSG_PONG, pong_message, NULL);
for (i=0;i<n;i++) {
message_send_pid(pid_to_procid(pid), MSG_PING, NULL, 0, True);
@@ -114,12 +99,16 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
size_t timelimit = n;
size_t ping_count = 0;
- printf("Sending pings for %d seconds\n", timelimit);
- while (timeval_elapsed(&tv) < timelimit) {
- if(message_send_pid(pid_to_procid(pid), MSG_PING,
- buf, 11, False)) ping_count++;
- if(message_send_pid(pid_to_procid(pid), MSG_PING,
- NULL, 0, False)) ping_count++;
+ printf("Sending pings for %d seconds\n", (int)timelimit);
+ while (timeval_elapsed(&tv) < timelimit) {
+ if(NT_STATUS_IS_OK(message_send_pid(pid_to_procid(pid),
+ MSG_PING,
+ buf, 11, False)))
+ ping_count++;
+ if(NT_STATUS_IS_OK(message_send_pid(pid_to_procid(pid),
+ MSG_PING,
+ NULL, 0, False)))
+ ping_count++;
while (ping_count > pong_count + 20) {
message_dispatch();
@@ -127,18 +116,18 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
}
printf("waiting for %d remaining replies (done %d)\n",
- ping_count - pong_count, pong_count);
+ (int)(ping_count - pong_count), pong_count);
while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
message_dispatch();
}
if (ping_count != pong_count) {
- fprintf(stderr, "ping test failed! received %d, sent %d\n",
- pong_count, ping_count);
+ fprintf(stderr, "ping test failed! received %d, sent "
+ "%d\n", pong_count, (int)ping_count);
}
printf("ping rate of %.0f messages/sec\n",
- (ping_count+pong_count)/timeval_elapsed(&tv));
+ (ping_count+pong_count)/timeval_elapsed(&tv));
}
return (0);
diff --git a/source/torture/nbio.c b/source/torture/nbio.c
index 795392ae5cb..9b2d58c86ee 100644
--- a/source/torture/nbio.c
+++ b/source/torture/nbio.c
@@ -34,7 +34,7 @@ static struct {
int handle;
} ftable[MAX_FILES];
-static struct {
+static struct children {
double bytes_in, bytes_out;
int line;
int done;
@@ -70,7 +70,7 @@ void nb_alarm(int ignore)
void nbio_shmem(int n)
{
nprocs = n;
- children = shm_setup(sizeof(*children) * nprocs);
+ children = (struct children *)shm_setup(sizeof(*children) * nprocs);
if (!children) {
printf("Failed to setup shared memory!\n");
exit(1);
diff --git a/source/torture/nsstest.c b/source/torture/nsstest.c
index d2b17f0f635..4b894fbfc34 100644
--- a/source/torture/nsstest.c
+++ b/source/torture/nsstest.c
@@ -62,7 +62,9 @@ static void report_nss_error(const char *who, NSS_STATUS status)
static struct passwd *nss_getpwent(void)
{
NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *,
- size_t , int *) = find_fn("getpwent_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(struct passwd *, char *,
+ size_t, int *))find_fn("getpwent_r");
static struct passwd pwd;
static char buf[1000];
NSS_STATUS status;
@@ -84,7 +86,9 @@ static struct passwd *nss_getpwent(void)
static struct passwd *nss_getpwnam(const char *name)
{
NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *,
- size_t , int *) = find_fn("getpwnam_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(const char *, struct passwd *, char *,
+ size_t, int *))find_fn("getpwnam_r");
static struct passwd pwd;
static char buf[1000];
NSS_STATUS status;
@@ -106,7 +110,9 @@ static struct passwd *nss_getpwnam(const char *name)
static struct passwd *nss_getpwuid(uid_t uid)
{
NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *,
- size_t , int *) = find_fn("getpwuid_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(uid_t, struct passwd *, char *,
+ size_t, int *))find_fn("getpwuid_r");
static struct passwd pwd;
static char buf[1000];
NSS_STATUS status;
@@ -127,7 +133,8 @@ static struct passwd *nss_getpwuid(uid_t uid)
static void nss_setpwent(void)
{
- NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent");
+ NSS_STATUS (*_nss_setpwent)(void) =
+ (NSS_STATUS(*)(void))find_fn("setpwent");
NSS_STATUS status;
if (!_nss_setpwent)
@@ -141,7 +148,8 @@ static void nss_setpwent(void)
static void nss_endpwent(void)
{
- NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent");
+ NSS_STATUS (*_nss_endpwent)(void) =
+ (NSS_STATUS (*)(void))find_fn("endpwent");
NSS_STATUS status;
if (!_nss_endpwent)
@@ -157,7 +165,9 @@ static void nss_endpwent(void)
static struct group *nss_getgrent(void)
{
NSS_STATUS (*_nss_getgrent_r)(struct group *, char *,
- size_t , int *) = find_fn("getgrent_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(struct group *, char *,
+ size_t, int *))find_fn("getgrent_r");
static struct group grp;
static char *buf;
static int buflen = 1024;
@@ -167,32 +177,37 @@ static struct group *nss_getgrent(void)
return NULL;
if (!buf)
- buf = SMB_MALLOC(buflen);
+ buf = SMB_MALLOC_ARRAY(char, buflen);
again:
status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno);
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
- buf = SMB_REALLOC(buf, buflen);
+ buf = SMB_REALLOC_ARRAY(buf, char, buflen);
if (!buf) {
return NULL;
}
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
return NULL;
}
if (status != NSS_STATUS_SUCCESS) {
report_nss_error("getgrent", status);
+ SAFE_FREE(buf);
return NULL;
}
+ SAFE_FREE(buf);
return &grp;
}
static struct group *nss_getgrnam(const char *name)
{
NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *,
- size_t , int *) = find_fn("getgrnam_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(const char *, struct group *, char *,
+ size_t, int *))find_fn("getgrnam_r");
static struct group grp;
static char *buf;
static int buflen = 1000;
@@ -202,12 +217,12 @@ static struct group *nss_getgrnam(const char *name)
return NULL;
if (!buf)
- buf = SMB_MALLOC(buflen);
+ buf = SMB_MALLOC_ARRAY(char, buflen);
again:
status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
- buf = SMB_REALLOC(buf, buflen);
+ buf = SMB_REALLOC_ARRAY(buf, char, buflen);
if (!buf) {
return NULL;
}
@@ -226,7 +241,9 @@ again:
static struct group *nss_getgrgid(gid_t gid)
{
NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *,
- size_t , int *) = find_fn("getgrgid_r");
+ size_t , int *) =
+ (NSS_STATUS (*)(gid_t, struct group *, char *,
+ size_t, int *))find_fn("getgrgid_r");
static struct group grp;
static char *buf;
static int buflen = 1000;
@@ -236,13 +253,13 @@ static struct group *nss_getgrgid(gid_t gid)
return NULL;
if (!buf)
- buf = SMB_MALLOC(buflen);
+ buf = SMB_MALLOC_ARRAY(char, buflen);
again:
status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
- buf = SMB_REALLOC(buf, buflen);
+ buf = SMB_REALLOC_ARRAY(buf, char, buflen);
if (!buf) {
return NULL;
}
@@ -260,7 +277,8 @@ again:
static void nss_setgrent(void)
{
- NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
+ NSS_STATUS (*_nss_setgrent)(void) =
+ (NSS_STATUS (*)(void))find_fn("setgrent");
NSS_STATUS status;
if (!_nss_setgrent)
@@ -274,7 +292,8 @@ static void nss_setgrent(void)
static void nss_endgrent(void)
{
- NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
+ NSS_STATUS (*_nss_endgrent)(void) =
+ (NSS_STATUS (*)(void))find_fn("endgrent");
NSS_STATUS status;
if (!_nss_endgrent)
@@ -290,7 +309,9 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta
{
NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *,
long int *, gid_t **, long int , int *) =
- find_fn("initgroups_dyn");
+ (NSS_STATUS (*)(char *, gid_t, long int *,
+ long int *, gid_t **,
+ long int, int *))find_fn("initgroups_dyn");
NSS_STATUS status;
if (!_nss_initgroups)
diff --git a/source/torture/pdbtest.c b/source/torture/pdbtest.c
new file mode 100644
index 00000000000..8b15f9629b9
--- /dev/null
+++ b/source/torture/pdbtest.c
@@ -0,0 +1,392 @@
+/*
+ Unix SMB/CIFS implementation.
+ passdb testing utility
+
+ Copyright (C) Wilco Baan Hofman 2006
+ Copyright (C) Jelmer Vernooij 2006
+
+ 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 BOOL samu_correct(struct samu *s1, struct samu *s2)
+{
+ BOOL ret = True;
+ uint32 s1_len, s2_len;
+ const char *s1_buf, *s2_buf;
+ const uint8 *d1_buf, *d2_buf;
+
+ /* Check Unix username */
+ s1_buf = pdb_get_username(s1);
+ s2_buf = pdb_get_username(s2);
+ if (s2_buf == NULL && s1_buf != NULL) {
+ DEBUG(0, ("Username is not set\n"));
+ ret = False;
+ } else if (s1_buf == NULL) {
+ /* Do nothing */
+ } else if (strcmp(s1_buf,s2_buf)) {
+ DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n",
+ pdb_get_username(s1),
+ pdb_get_username(s2)));
+ ret = False;
+ }
+
+ /* Check NT username */
+ s1_buf = pdb_get_nt_username(s1);
+ s2_buf = pdb_get_nt_username(s2);
+ if (s2_buf == NULL && s1_buf != NULL) {
+ DEBUG(0, ("NT Username is not set\n"));
+ ret = False;
+ } else if (s1_buf == NULL) {
+ /* Do nothing */
+ } else if (strcmp(s1_buf, s2_buf)) {
+ DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n",
+ pdb_get_nt_username(s1),
+ pdb_get_nt_username(s2)));
+ ret = False;
+ }
+
+ /* Check acct ctrl */
+ if (pdb_get_acct_ctrl(s1) != pdb_get_acct_ctrl(s2)) {
+ DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n",
+ pdb_get_acct_ctrl(s1),
+ pdb_get_acct_ctrl(s1),
+ pdb_get_acct_ctrl(s2),
+ pdb_get_acct_ctrl(s2)));
+ ret = False;
+ }
+
+ /* Check NT password */
+ d1_buf = pdb_get_nt_passwd(s1);
+ d2_buf = pdb_get_nt_passwd(s2);
+ if (d2_buf == NULL && d1_buf != NULL) {
+ DEBUG(0, ("NT password is not set\n"));
+ ret = False;
+ } else if (d1_buf == NULL) {
+ /* Do nothing */
+ } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
+ DEBUG(0, ("NT password not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check lanman password */
+ d1_buf = pdb_get_lanman_passwd(s1);
+ d2_buf = pdb_get_lanman_passwd(s2);
+ if (d2_buf == NULL && d1_buf != NULL) {
+ DEBUG(0, ("Lanman password is not set\n"));
+ } else if (d1_buf == NULL) {
+ /* Do nothing */
+ } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
+ DEBUG(0, ("Lanman password not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check password history */
+ d1_buf = pdb_get_pw_history(s1, &s1_len);
+ d2_buf = pdb_get_pw_history(s2, &s2_len);
+ if (d2_buf == NULL && d1_buf != NULL) {
+ DEBUG(0, ("Password history is not set\n"));
+ } else if (d1_buf == NULL) {
+ /* Do nothing */
+ } else if (s1_len != s1_len) {
+ DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n",
+ s1_len, s2_len));
+ ret = False;
+ } else if (strncmp(s1_buf, s2_buf, s1_len)) {
+ DEBUG(0, ("Password history not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check logon time */
+ if (pdb_get_logon_time(s1) != pdb_get_logon_time(s2)) {
+ DEBUG(0, ("Logon time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check logoff time */
+ if (pdb_get_logoff_time(s1) != pdb_get_logoff_time(s2)) {
+ DEBUG(0, ("Logoff time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check kickoff time */
+ if (pdb_get_kickoff_time(s1) != pdb_get_logoff_time(s2)) {
+ DEBUG(0, ("Kickoff time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check bad password time */
+ if (pdb_get_bad_password_time(s1) != pdb_get_bad_password_time(s2)) {
+ DEBUG(0, ("Bad password time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check password last set time */
+ if (pdb_get_pass_last_set_time(s1) != pdb_get_pass_last_set_time(s2)) {
+ DEBUG(0, ("Password last set time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check password can change time */
+ if (pdb_get_pass_can_change_time(s1) != pdb_get_pass_can_change_time(s2)) {
+ DEBUG(0, ("Password can change time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check password must change time */
+ if (pdb_get_pass_must_change_time(s1) != pdb_get_pass_must_change_time(s2)) {
+ DEBUG(0, ("Password must change time is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check logon divs */
+ if (pdb_get_logon_divs(s1) != pdb_get_logon_divs(s2)) {
+ DEBUG(0, ("Logon divs not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check logon hours */
+ if (pdb_get_hours_len(s1) != pdb_get_hours_len(s2)) {
+ DEBUG(0, ("Logon hours length not written correctly\n"));
+ ret = False;
+ } else if (pdb_get_hours_len(s1) != 0) {
+ d1_buf = pdb_get_hours(s1);
+ d2_buf = pdb_get_hours(s2);
+ if (d2_buf == NULL && d2_buf != NULL) {
+ DEBUG(0, ("Logon hours is not set\n"));
+ ret = False;
+ } else if (d1_buf == NULL) {
+ /* Do nothing */
+ } else if (memcmp(d1_buf, d2_buf, MAX_HOURS_LEN)) {
+ DEBUG(0, ("Logon hours is not written correctly\n"));
+ ret = False;
+ }
+ }
+
+ /* Check profile path */
+ s1_buf = pdb_get_profile_path(s1);
+ s2_buf = pdb_get_profile_path(s2);
+ if (s2_buf == NULL && s1_buf != NULL) {
+ DEBUG(0, ("Profile path is not set\n"));
+ ret = False;
+ } else if (s1_buf == NULL) {
+ /* Do nothing */
+ } else if (strcmp(s1_buf, s2_buf)) {
+ DEBUG(0, ("Profile path is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check home dir */
+ s1_buf = pdb_get_homedir(s1);
+ s2_buf = pdb_get_homedir(s2);
+ if (s2_buf == NULL && s1_buf != NULL) {
+ DEBUG(0, ("Home dir is not set\n"));
+ ret = False;
+ } else if (s1_buf == NULL) {
+ /* Do nothing */
+ } else if (strcmp(s1_buf, s2_buf)) {
+ DEBUG(0, ("Home dir is not written correctly\n"));
+ ret = False;
+ }
+
+ /* Check logon script */
+ s1_buf = pdb_get_logon_script(s1);
+ s2_buf = pdb_get_logon_script(s2);
+ if (s2_buf == NULL && s1_buf != NULL) {
+ DEBUG(0, ("Logon script not set\n"));
+ ret = False;
+ } else if (s1_buf == NULL) {
+ /* Do nothing */
+ } else if (strcmp(s1_buf, s2_buf)) {
+ DEBUG(0, ("Logon script is not written correctly\n"));
+ ret = False;
+ }
+
+ /* TODO Check user and group sids */
+
+ return ret;
+}
+
+
+int main(int argc, char **argv)
+{
+ TALLOC_CTX *ctx;
+ struct samu *out = NULL;
+ struct samu *in = NULL;
+ NTSTATUS rv;
+ int i;
+ struct timeval tv;
+ BOOL error = False;
+ struct passwd *pwd;
+ uint8 *buf;
+ uint32 expire, min_age, history;
+ struct pdb_methods *pdb;
+ poptContext pc;
+ static char *backend = NULL;
+ static const char *unix_user = "nobody";
+ struct poptOption long_options[] = {
+ {"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" },
+ {"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
+ POPT_AUTOHELP
+ POPT_COMMON_SAMBA
+ POPT_TABLEEND
+ };
+
+ load_case_tables();
+
+ pc = poptGetContext("vfstest", argc, (const char **) argv,
+ long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "backend[:settings] username");
+
+ while(poptGetNextOpt(pc) != -1);
+
+ poptFreeContext(pc);
+
+ /* Load configuration */
+ lp_load(dyn_CONFIGFILE, False, False, True, True);
+ setup_logging("pdbtest", True);
+
+ if (backend == NULL) {
+ backend = lp_passdb_backend();
+ }
+
+ rv = make_pdb_method_name(&pdb, backend);
+ if (NT_STATUS_IS_ERR(rv)) {
+ fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv));
+ exit(1);
+ }
+
+ ctx = talloc_init("PDBTEST");
+
+ if (!(out = samu_new(ctx))) {
+ fprintf(stderr, "Can't create samu structure.\n");
+ exit(1);
+ }
+
+ if ((pwd = getpwnam_alloc(ctx, unix_user)) == NULL) {
+ fprintf(stderr, "Error getting user information for %s\n", unix_user);
+ exit(1);
+ }
+
+ samu_set_unix(out, pwd);
+
+ pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET);
+ pdb_set_homedir(out, "\\\\torture\\home", PDB_SET);
+ pdb_set_logon_script(out, "torture_script.cmd", PDB_SET);
+
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &history);
+ if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) {
+ buf = (uint8 *)TALLOC(ctx, NT_HASH_LEN);
+ } else {
+ buf = (uint8 *)TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN);
+ }
+
+ /* Generate some random hashes */
+ GetTimeOfDay(&tv);
+ srand(tv.tv_usec);
+ for (i = 0; i < NT_HASH_LEN; i++) {
+ buf[i] = (uint8) rand();
+ }
+ pdb_set_nt_passwd(out, buf, PDB_SET);
+ for (i = 0; i < LM_HASH_LEN; i++) {
+ buf[i] = (uint8) rand();
+ }
+ pdb_set_lanman_passwd(out, buf, PDB_SET);
+ for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) {
+ buf[i] = (uint8) rand();
+ }
+ pdb_set_pw_history(out, buf, history, PDB_SET);
+
+ pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire);
+ pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age);
+ pdb_set_pass_last_set_time(out, time(NULL), PDB_SET);
+
+ if (expire == 0 || expire == (uint32)-1) {
+ pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET);
+ } else {
+ pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET);
+ }
+
+ if (min_age == (uint32)-1) {
+ pdb_set_pass_can_change_time(out, 0, PDB_SET);
+ } else {
+ pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET);
+ }
+
+ /* Create account */
+ if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) {
+ fprintf(stderr, "Error in add_sam_account: %s\n",
+ get_friendly_nt_error_msg(rv));
+ exit(1);
+ }
+
+ if (!(in = samu_new(ctx))) {
+ fprintf(stderr, "Can't create samu structure.\n");
+ exit(1);
+ }
+
+ /* Get account information through getsampwnam() */
+ if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) {
+ fprintf(stderr, "Error getting sampw of added user %s.\n",
+ out->username);
+ if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
+ fprintf(stderr, "Error in delete_sam_account %s\n",
+ get_friendly_nt_error_msg(rv));
+ }
+ TALLOC_FREE(ctx);
+ }
+
+ /* Verify integrity */
+ if (samu_correct(out, in)) {
+ printf("User info written correctly\n");
+ } else {
+ printf("User info NOT written correctly\n");
+ error = True;
+ }
+
+ /* Delete account */
+ if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
+ fprintf(stderr, "Error in delete_sam_account %s\n",
+ get_friendly_nt_error_msg(rv));
+ }
+
+ pdb->setsampwent(pdb, False, 0);
+ while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) {
+ if (pdb_get_username(out) == NULL) {
+ fprintf(stderr, "Got bad username through getsampwent()\n");
+ error = True;
+ break;
+ }
+ if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) {
+ fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n");
+ error = True;
+ continue;
+ }
+ if (!samu_correct(out, in)) {
+ printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n");
+ }
+ }
+ pdb->endsampwent(pdb);
+
+ TALLOC_FREE(ctx);
+
+ if (error) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/source/torture/rpctorture.c b/source/torture/rpctorture.c
index d69cc8eb8df..98f2dc105fa 100644
--- a/source/torture/rpctorture.c
+++ b/source/torture/rpctorture.c
@@ -493,7 +493,7 @@ enum client_action
strupper_m(global_myname);
fstrcpy(cli_info.myhostname, global_myname);
- DEBUG(3,("%s client started (version %s)\n",timestring(False),SAMBA_VERSION_STRING));
+ DEBUG(3,("%s client started (version %s)\n",current_timestring(False),SAMBA_VERSION_STRING));
if (*smb_cli->domain == 0)
{
diff --git a/source/torture/scanner.c b/source/torture/scanner.c
index 1893be83699..87c82f8a737 100644
--- a/source/torture/scanner.c
+++ b/source/torture/scanner.c
@@ -49,7 +49,7 @@ static NTSTATUS try_trans2(struct cli_state *cli,
int op,
char *param, char *data,
int param_len, int data_len,
- int *rparam_len, int *rdata_len)
+ unsigned int *rparam_len, unsigned int *rdata_len)
{
uint16 setup = op;
char *rparam=NULL, *rdata=NULL;
@@ -80,7 +80,7 @@ static NTSTATUS try_trans2_len(struct cli_state *cli,
int op, int level,
char *param, char *data,
int param_len, int *data_len,
- int *rparam_len, int *rdata_len)
+ unsigned int *rparam_len, unsigned int *rdata_len)
{
NTSTATUS ret=NT_STATUS_OK;
@@ -115,7 +115,7 @@ static BOOL scan_trans2(struct cli_state *cli, int op, int level,
{
int data_len = 0;
int param_len = 0;
- int rparam_len, rdata_len;
+ unsigned int rparam_len, rdata_len;
pstring param, data;
NTSTATUS status;
@@ -196,7 +196,7 @@ BOOL torture_trans2_scan(int dummy)
printf("starting trans2 scan test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -253,7 +253,7 @@ static NTSTATUS try_nttrans(struct cli_state *cli,
int op,
char *param, char *data,
int param_len, int data_len,
- int *rparam_len, int *rdata_len)
+ unsigned int *rparam_len, unsigned int *rdata_len)
{
char *rparam=NULL, *rdata=NULL;
@@ -282,7 +282,7 @@ static NTSTATUS try_nttrans_len(struct cli_state *cli,
int op, int level,
char *param, char *data,
int param_len, int *data_len,
- int *rparam_len, int *rdata_len)
+ unsigned int *rparam_len, unsigned int *rdata_len)
{
NTSTATUS ret=NT_STATUS_OK;
@@ -317,7 +317,7 @@ static BOOL scan_nttrans(struct cli_state *cli, int op, int level,
{
int data_len = 0;
int param_len = 0;
- int rparam_len, rdata_len;
+ unsigned int rparam_len, rdata_len;
pstring param, data;
NTSTATUS status;
@@ -398,7 +398,7 @@ BOOL torture_nttrans_scan(int dummy)
printf("starting nttrans scan test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
diff --git a/source/torture/torture.c b/source/torture/torture.c
index a8a8e847fbb..79444946122 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -36,6 +36,8 @@ static BOOL use_oplocks;
static BOOL use_level_II_oplocks;
static const char *client_txt = "client_oplocks.txt";
static BOOL use_kerberos;
+static fstring multishare_conn_fname;
+static BOOL use_multishare_conn = False;
BOOL torture_showall = False;
@@ -44,6 +46,7 @@ static double create_procs(BOOL (*fn)(int), BOOL *result);
static struct timeval tp1,tp2;
+
void start_timer(void)
{
GetTimeOfDay(&tp1);
@@ -94,28 +97,27 @@ void *shm_setup(int size)
}
-static BOOL open_nbt_connection(struct cli_state *c)
+static struct cli_state *open_nbt_connection(void)
{
struct nmb_name called, calling;
struct in_addr ip;
-
- ZERO_STRUCTP(c);
+ struct cli_state *c;
make_nmb_name(&calling, myname, 0x0);
make_nmb_name(&called , host, 0x20);
zero_ip(&ip);
- if (!cli_initialise(c)) {
+ if (!(c = cli_initialise())) {
printf("Failed initialize cli_struct to connect with %s\n", host);
- return False;
+ return NULL;
}
c->port = port_to_use;
if (!cli_connect(c, host, &ip)) {
printf("Failed to connect with %s\n", host);
- return False;
+ return NULL;
}
c->use_kerberos = use_kerberos;
@@ -131,7 +133,7 @@ static BOOL open_nbt_connection(struct cli_state *c)
*/
if (!cli_connect(c, host, &ip)) {
printf("Failed to connect with %s\n", host);
- return False;
+ return NULL;
}
make_nmb_name(&called, "*SMBSERVER", 0x20);
@@ -140,14 +142,74 @@ static BOOL open_nbt_connection(struct cli_state *c)
printf("We tried with a called name of %s & %s\n",
host, "*SMBSERVER");
cli_shutdown(c);
- return False;
+ return NULL;
}
}
- return True;
+ return c;
+}
+
+/* Insert a NULL at the first separator of the given path and return a pointer
+ * to the remainder of the string.
+ */
+static char *
+terminate_path_at_separator(char * path)
+{
+ char * p;
+
+ if (!path) {
+ return NULL;
+ }
+
+ if ((p = strchr_m(path, '/'))) {
+ *p = '\0';
+ return p + 1;
+ }
+
+ if ((p = strchr_m(path, '\\'))) {
+ *p = '\0';
+ return p + 1;
+ }
+
+ /* No separator. */
+ return NULL;
+}
+
+/*
+ parse a //server/share type UNC name
+*/
+BOOL smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
+ char **hostname, char **sharename)
+{
+ char *p;
+
+ *hostname = *sharename = NULL;
+
+ if (strncmp(unc_name, "\\\\", 2) &&
+ strncmp(unc_name, "//", 2)) {
+ return False;
+ }
+
+ *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
+ p = terminate_path_at_separator(*hostname);
+
+ if (p && *p) {
+ *sharename = talloc_strdup(mem_ctx, p);
+ terminate_path_at_separator(*sharename);
+ }
+
+ if (*hostname && *sharename) {
+ return True;
+ }
+
+ TALLOC_FREE(*hostname);
+ TALLOC_FREE(*sharename);
+ return False;
}
-BOOL torture_open_connection(struct cli_state **c)
+static BOOL torture_open_connection_share(struct cli_state **c,
+ const char *hostname,
+ const char *sharename)
{
BOOL retry;
int flags = 0;
@@ -155,13 +217,15 @@ BOOL torture_open_connection(struct cli_state **c)
if (use_kerberos)
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
-
+
status = cli_full_connection(c, myname,
- host, NULL, port_to_use,
- share, "?????",
+ hostname, NULL, port_to_use,
+ sharename, "?????",
username, workgroup,
password, flags, Undefined, &retry);
if (!NT_STATUS_IS_OK(status)) {
+ printf("failed to open share connection: //%s/%s port:%d - %s\n",
+ hostname, sharename, port_to_use, nt_errstr(status));
return False;
}
@@ -172,6 +236,47 @@ BOOL torture_open_connection(struct cli_state **c)
return True;
}
+void torture_open_connection_free_unclist(char **unc_list)
+{
+ if (unc_list!=NULL)
+ {
+ SAFE_FREE(unc_list[0]);
+ SAFE_FREE(unc_list);
+ }
+}
+
+BOOL torture_open_connection(struct cli_state **c, int conn_index)
+{
+ char **unc_list = NULL;
+ int num_unc_names = 0;
+ BOOL result;
+
+ if (use_multishare_conn==True) {
+ char *h, *s;
+ unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0);
+ if (!unc_list || num_unc_names <= 0) {
+ printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
+ exit(1);
+ }
+
+ if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
+ NULL, &h, &s)) {
+ printf("Failed to parse UNC name %s\n",
+ unc_list[conn_index % num_unc_names]);
+ torture_open_connection_free_unclist(unc_list);
+ exit(1);
+ }
+
+ result = torture_open_connection_share(c, h, s);
+
+ /* h, s were copied earlier */
+ torture_open_connection_free_unclist(unc_list);
+ return result;
+ }
+
+ return torture_open_connection_share(c, host, share);
+}
+
BOOL torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
{
uint16 old_vuid = cli->vuid;
@@ -181,7 +286,10 @@ BOOL torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
fstrcpy(old_user_name, cli->user_name);
cli->vuid = 0;
- ret = cli_session_setup(cli, username, password, passlen, password, passlen, workgroup);
+ ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
+ password, passlen,
+ password, passlen,
+ workgroup));
*new_vuid = cli->vuid;
cli->vuid = old_vuid;
fstrcpy(cli->user_name, old_user_name);
@@ -462,8 +570,8 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
int fnum1;
int fnum2;
int i;
- uchar buf[131072];
- uchar buf_rd[131072];
+ char buf[131072];
+ char buf_rd[131072];
BOOL correct = True;
ssize_t bytes_read;
@@ -494,7 +602,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
printf("%d\r", i); fflush(stdout);
}
- generate_random_buffer(buf, buf_size);
+ generate_random_buffer((unsigned char *)buf, buf_size);
if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
printf("write failed (%s)\n", cli_errstr(c1));
@@ -504,7 +612,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
printf("read failed (%s)\n", cli_errstr(c2));
- printf("read %d, expected %ld\n", bytes_read,
+ printf("read %d, expected %ld\n", (int)bytes_read,
(unsigned long)buf_size);
correct = False;
break;
@@ -540,7 +648,7 @@ static BOOL run_readwritetest(int dummy)
static struct cli_state *cli1, *cli2;
BOOL test1, test2 = False;
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
cli_sockopt(cli1, sockops);
@@ -595,7 +703,7 @@ static BOOL run_readwritelarge(int dummy)
char buf[126*1024];
BOOL correct = True;
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
cli_sockopt(cli1, sockops);
@@ -826,7 +934,7 @@ static BOOL run_locktest1(int dummy)
time_t t1, t2;
unsigned lock_timeout;
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
cli_sockopt(cli1, sockops);
@@ -941,7 +1049,7 @@ static BOOL run_tcon_test(int dummy)
char buf[4];
BOOL ret = True;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
cli_sockopt(cli, sockops);
@@ -1043,7 +1151,7 @@ static BOOL run_tcon2_test(int dummy)
char *service;
NTSTATUS status;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
cli_sockopt(cli, sockops);
@@ -1196,7 +1304,7 @@ static BOOL run_locktest2(int dummy)
int fnum1, fnum2, fnum3;
BOOL correct = True;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -1335,7 +1443,7 @@ static BOOL run_locktest3(int dummy)
#define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
cli_sockopt(cli1, sockops);
@@ -1459,7 +1567,7 @@ static BOOL run_locktest4(int dummy)
char buf[1000];
BOOL correct = True;
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
@@ -1630,7 +1738,7 @@ static BOOL run_locktest5(int dummy)
char buf[1000];
BOOL correct = True;
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
@@ -1753,7 +1861,7 @@ static BOOL run_locktest6(int dummy)
int fnum;
NTSTATUS status;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -1793,7 +1901,7 @@ static BOOL run_locktest7(int dummy)
char buf[200];
BOOL correct = False;
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -1929,7 +2037,7 @@ static BOOL run_fdpasstest(int dummy)
int fnum1;
pstring buf;
- if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
return False;
}
cli_sockopt(cli1, sockops);
@@ -1984,7 +2092,7 @@ static BOOL run_fdsesstest(int dummy)
pstring buf;
BOOL ret = True;
- if (!torture_open_connection(&cli))
+ if (!torture_open_connection(&cli, 0))
return False;
cli_sockopt(cli, sockops);
@@ -2066,7 +2174,7 @@ static BOOL run_unlinktest(int dummy)
int fnum;
BOOL correct = True;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -2174,20 +2282,20 @@ static void rand_buf(char *buf, int len)
static BOOL run_negprot_nowait(int dummy)
{
int i;
- static struct cli_state cli;
+ static struct cli_state *cli;
BOOL correct = True;
printf("starting negprot nowait test\n");
- if (!open_nbt_connection(&cli)) {
+ if (!(cli = open_nbt_connection())) {
return False;
}
for (i=0;i<50000;i++) {
- cli_negprot_send(&cli);
+ cli_negprot_send(cli);
}
- if (!torture_close_connection(&cli)) {
+ if (!torture_close_connection(cli)) {
correct = False;
}
@@ -2202,7 +2310,7 @@ static BOOL run_randomipc(int dummy)
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
pstring param;
int api, param_len, i;
struct cli_state *cli;
@@ -2211,7 +2319,7 @@ static BOOL run_randomipc(int dummy)
printf("starting random ipc test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -2264,7 +2372,7 @@ static BOOL run_browsetest(int dummy)
printf("starting browse test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -2302,7 +2410,7 @@ static BOOL run_attrtest(int dummy)
printf("starting attrib test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -2361,7 +2469,8 @@ static BOOL run_trans2test(int dummy)
struct cli_state *cli;
int fnum;
SMB_OFF_T size;
- time_t c_time, a_time, m_time, w_time, m_time2;
+ time_t c_time, a_time, m_time;
+ struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
const char *fname = "\\trans2.tst";
const char *dname = "\\trans2";
const char *fname2 = "\\trans2\\trans2.tst";
@@ -2370,15 +2479,15 @@ static BOOL run_trans2test(int dummy)
printf("starting trans2 test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
cli_unlink(cli, fname);
fnum = cli_open(cli, fname,
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- if (!cli_qfileinfo(cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
- NULL, NULL)) {
+ if (!cli_qfileinfo(cli, fnum, NULL, &size, &c_time_ts, &a_time_ts, &w_time_ts,
+ &m_time_ts, NULL)) {
printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli));
correct = False;
}
@@ -2433,13 +2542,13 @@ static BOOL run_trans2test(int dummy)
fnum = cli_open(cli, fname,
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
cli_close(cli, fnum);
- if (!cli_qpathinfo2(cli, fname, &c_time, &a_time, &w_time,
- &m_time, &size, NULL, NULL)) {
+ if (!cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
+ &m_time_ts, &size, NULL, NULL)) {
printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
correct = False;
} else {
- if (w_time < 60*60*24*2) {
- printf("write time=%s", ctime(&w_time));
+ if (w_time_ts.tv_sec < 60*60*24*2) {
+ printf("write time=%s", ctime(&w_time_ts.tv_sec));
printf("This system appears to set a initial 0 write time\n");
correct = False;
}
@@ -2455,8 +2564,8 @@ static BOOL run_trans2test(int dummy)
correct = False;
}
sleep(3);
- if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time, &a_time, &w_time,
- &m_time, &size, NULL, NULL)) {
+ if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
+ &m_time_ts, &size, NULL, NULL)) {
printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
correct = False;
}
@@ -2465,12 +2574,13 @@ static BOOL run_trans2test(int dummy)
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
cli_write(cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
cli_close(cli, fnum);
- if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time, &a_time, &w_time,
- &m_time2, &size, NULL, NULL)) {
+ if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
+ &m_time2_ts, &size, NULL, NULL)) {
printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
correct = False;
} else {
- if (m_time2 == m_time) {
+ if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
+ == 0) {
printf("This system does not update directory modification times\n");
correct = False;
}
@@ -2519,7 +2629,7 @@ static BOOL run_w2ktest(int dummy)
printf("starting w2k test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -2554,7 +2664,7 @@ static BOOL run_oplock1(int dummy)
printf("starting oplock test 1\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -2612,7 +2722,7 @@ static BOOL run_oplock2(int dummy)
printf("starting oplock test 2\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
use_level_II_oplocks = False;
use_oplocks = saved_use_oplocks;
return False;
@@ -2621,7 +2731,7 @@ static BOOL run_oplock2(int dummy)
cli1->use_oplocks = True;
cli1->use_level_II_oplocks = True;
- if (!torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli2, 1)) {
use_level_II_oplocks = False;
use_oplocks = saved_use_oplocks;
return False;
@@ -2755,7 +2865,7 @@ static BOOL run_oplock3(int dummy)
/* Child code */
use_oplocks = True;
use_level_II_oplocks = True;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
*shared_correct = False;
exit(0);
}
@@ -2769,7 +2879,7 @@ static BOOL run_oplock3(int dummy)
/* parent code */
use_oplocks = True;
use_level_II_oplocks = True;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 1)) { /* other is forked */
return False;
}
cli_oplock_handler(cli, oplock3_handler);
@@ -2802,7 +2912,7 @@ static BOOL run_deletetest(int dummy)
printf("starting delete test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -3116,7 +3226,7 @@ static BOOL run_deletetest(int dummy)
cli_setatr(cli1, fname, 0, 0);
cli_unlink(cli1, fname);
- if (!torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli2, 1)) {
printf("[8] failed to open second connection.\n");
correct = False;
goto fail;
@@ -3283,7 +3393,7 @@ static BOOL run_properties(int dummy)
ZERO_STRUCT(cli);
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -3331,7 +3441,7 @@ static BOOL run_xcopy(int dummy)
printf("starting xcopy test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -3374,7 +3484,7 @@ static BOOL run_rename(int dummy)
printf("starting rename test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -3560,7 +3670,7 @@ static BOOL run_pipe_number(int dummy)
int num_pipes = 0;
printf("starting pipenumber test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -3574,6 +3684,7 @@ static BOOL run_pipe_number(int dummy)
break;
}
num_pipes++;
+ printf("\r%6d", num_pipes);
}
printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
@@ -3597,7 +3708,7 @@ static BOOL run_opentest(int dummy)
printf("starting open test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -3744,7 +3855,7 @@ static BOOL run_opentest(int dummy)
/* Test the non-io opens... */
- if (!torture_open_connection(&cli2)) {
+ if (!torture_open_connection(&cli2, 1)) {
return False;
}
@@ -4045,7 +4156,7 @@ static BOOL run_openattrtest(int dummy)
printf("starting open attr test\n");
- if (!torture_open_connection(&cli1)) {
+ if (!torture_open_connection(&cli1, 0)) {
return False;
}
@@ -4157,7 +4268,7 @@ static BOOL run_dirtest(int dummy)
printf("starting directory test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -4230,7 +4341,7 @@ BOOL torture_ioctl_test(int dummy)
DATA_BLOB blob;
NTSTATUS status;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -4258,7 +4369,8 @@ BOOL torture_ioctl_test(int dummy)
status = cli_raw_ioctl(cli, fnum, code, &blob);
if (NT_STATUS_IS_OK(status)) {
- printf("ioctl 0x%x OK : %d bytes\n", code, blob.length);
+ printf("ioctl 0x%x OK : %d bytes\n", (int)code,
+ (int)blob.length);
data_blob_free(&blob);
}
}
@@ -4281,7 +4393,7 @@ BOOL torture_chkpath_test(int dummy)
int fnum;
BOOL ret;
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -4366,7 +4478,7 @@ static BOOL run_eatest(int dummy)
printf("starting eatest\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -4409,7 +4521,7 @@ static BOOL run_eatest(int dummy)
correct = False;
}
- printf("num_eas = %d\n", num_eas);
+ printf("num_eas = %d\n", (int)num_eas);
if (num_eas != 20) {
printf("Should be 20 EA's stored... failing.\n");
@@ -4418,7 +4530,8 @@ static BOOL run_eatest(int dummy)
for (i = 0; i < num_eas; i++) {
printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
- dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+ dump_data(0, (char *)ea_list[i].value.data,
+ ea_list[i].value.length);
}
/* Setting EA's to zero length deletes them. Test this */
@@ -4442,10 +4555,11 @@ static BOOL run_eatest(int dummy)
correct = False;
}
- printf("num_eas = %d\n", num_eas);
+ printf("num_eas = %d\n", (int)num_eas);
for (i = 0; i < num_eas; i++) {
printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
- dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+ dump_data(0, (char *)ea_list[i].value.data,
+ ea_list[i].value.length);
}
if (num_eas != 0) {
@@ -4476,7 +4590,7 @@ static BOOL run_dirtest1(int dummy)
printf("starting directory test\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -4550,8 +4664,8 @@ static BOOL run_dirtest1(int dummy)
static BOOL run_error_map_extract(int dummy) {
- static struct cli_state c_dos;
- static struct cli_state c_nt;
+ static struct cli_state *c_dos;
+ static struct cli_state *c_nt;
uint32 error;
@@ -4564,81 +4678,81 @@ static BOOL run_error_map_extract(int dummy) {
/* NT-Error connection */
- if (!open_nbt_connection(&c_nt)) {
+ if (!(c_nt = open_nbt_connection())) {
return False;
}
- c_nt.use_spnego = False;
+ c_nt->use_spnego = False;
- if (!cli_negprot(&c_nt)) {
- printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(&c_nt));
- cli_shutdown(&c_nt);
+ if (!cli_negprot(c_nt)) {
+ printf("%s rejected the NT-error negprot (%s)\n",host, cli_errstr(c_nt));
+ cli_shutdown(c_nt);
return False;
}
- if (!cli_session_setup(&c_nt, "", "", 0, "", 0,
- workgroup)) {
- printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(&c_nt));
+ if (!NT_STATUS_IS_OK(cli_session_setup(c_nt, "", "", 0, "", 0,
+ workgroup))) {
+ printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
return False;
}
/* DOS-Error connection */
- if (!open_nbt_connection(&c_dos)) {
+ if (!(c_dos = open_nbt_connection())) {
return False;
}
- c_dos.use_spnego = False;
- c_dos.force_dos_errors = True;
+ c_dos->use_spnego = False;
+ c_dos->force_dos_errors = True;
- if (!cli_negprot(&c_dos)) {
- printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(&c_dos));
- cli_shutdown(&c_dos);
+ if (!cli_negprot(c_dos)) {
+ printf("%s rejected the DOS-error negprot (%s)\n",host, cli_errstr(c_dos));
+ cli_shutdown(c_dos);
return False;
}
- if (!cli_session_setup(&c_dos, "", "", 0, "", 0,
- workgroup)) {
- printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(&c_dos));
+ if (!NT_STATUS_IS_OK(cli_session_setup(c_dos, "", "", 0, "", 0,
+ workgroup))) {
+ printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
return False;
}
for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
fstr_sprintf(user, "%X", error);
- if (cli_session_setup(&c_nt, user,
- password, strlen(password),
- password, strlen(password),
- workgroup)) {
+ if (NT_STATUS_IS_OK(cli_session_setup(c_nt, user,
+ password, strlen(password),
+ password, strlen(password),
+ workgroup))) {
printf("/** Session setup succeeded. This shouldn't happen...*/\n");
}
- flgs2 = SVAL(c_nt.inbuf,smb_flg2);
+ flgs2 = SVAL(c_nt->inbuf,smb_flg2);
/* Case #1: 32-bit NT errors */
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
- nt_status = NT_STATUS(IVAL(c_nt.inbuf,smb_rcls));
+ nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
} else {
printf("/** Dos error on NT connection! (%s) */\n",
- cli_errstr(&c_nt));
+ cli_errstr(c_nt));
nt_status = NT_STATUS(0xc0000000);
}
- if (cli_session_setup(&c_dos, user,
- password, strlen(password),
- password, strlen(password),
- workgroup)) {
+ if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user,
+ password, strlen(password),
+ password, strlen(password),
+ workgroup))) {
printf("/** Session setup succeeded. This shouldn't happen...*/\n");
}
- flgs2 = SVAL(c_dos.inbuf,smb_flg2), errnum;
+ flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
/* Case #1: 32-bit NT errors */
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
printf("/** NT error on DOS connection! (%s) */\n",
- cli_errstr(&c_nt));
+ cli_errstr(c_nt));
errnum = errclass = 0;
} else {
- cli_dos_error(&c_dos, &errclass, &errnum);
+ cli_dos_error(c_dos, &errclass, &errnum);
}
if (NT_STATUS_V(nt_status) != error) {
@@ -4655,6 +4769,101 @@ static BOOL run_error_map_extract(int dummy) {
return True;
}
+static BOOL run_local_substitute(int dummy)
+{
+ TALLOC_CTX *mem_ctx;
+ int diff = 0;
+
+ if ((mem_ctx = talloc_init("run_local_subst")) == NULL) {
+ printf("talloc_init failed\n");
+ return False;
+ }
+
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%U", "bla", "", -1, -1),
+ "bla");
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%u%U", "bla", "", -1, -1),
+ "blabla");
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, -1),
+ "NO_GROUP");
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, -1),
+ "NO_GROUP");
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%g", "", "", -1, 0),
+ gidtoname(0));
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%G", "", "", -1, 0),
+ gidtoname(0));
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%D%u", "u", "dom", -1, 0),
+ "domu");
+ diff |= strcmp(talloc_sub_specified(mem_ctx, "%i %I", "", "", -1, -1),
+ "0.0.0.0 0.0.0.0");
+
+ /* Different captialization rules in sub_basic... */
+
+ diff |= strcmp(talloc_sub_basic(mem_ctx, "BLA", "dom", "%U%D"),
+ "blaDOM");
+
+ TALLOC_FREE(mem_ctx);
+ return (diff == 0);
+}
+
+static BOOL run_local_gencache(int dummy)
+{
+ char *val;
+ time_t tm;
+
+ if (!gencache_init()) {
+ d_printf("%s: gencache_init() failed\n", __location__);
+ return False;
+ }
+
+ if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
+ d_printf("%s: gencache_set() failed\n", __location__);
+ return False;
+ }
+
+ if (!gencache_get("foo", &val, &tm)) {
+ d_printf("%s: gencache_get() failed\n", __location__);
+ return False;
+ }
+
+ if (strcmp(val, "bar") != 0) {
+ d_printf("%s: gencache_get() returned %s, expected %s\n",
+ __location__, val, "bar");
+ SAFE_FREE(val);
+ return False;
+ }
+
+ SAFE_FREE(val);
+
+ if (!gencache_del("foo")) {
+ d_printf("%s: gencache_del() failed\n", __location__);
+ return False;
+ }
+ if (gencache_del("foo")) {
+ d_printf("%s: second gencache_del() succeeded\n",
+ __location__);
+ return False;
+ }
+
+ if (gencache_get("foo", &val, &tm)) {
+ d_printf("%s: gencache_get() on deleted entry "
+ "succeeded\n", __location__);
+ return False;
+ }
+
+ if (!gencache_shutdown()) {
+ d_printf("%s: gencache_shutdown() failed\n", __location__);
+ return False;
+ }
+
+ if (gencache_shutdown()) {
+ d_printf("%s: second gencache_shutdown() succeeded\n",
+ __location__);
+ return False;
+ }
+
+ return True;
+}
+
static double create_procs(BOOL (*fn)(int), BOOL *result)
{
int i, status;
@@ -4693,7 +4902,7 @@ static double create_procs(BOOL (*fn)(int), BOOL *result)
slprintf(myname,sizeof(myname),"CLIENT%d", i);
while (1) {
- if (torture_open_connection(&current_cli)) break;
+ if (torture_open_connection(&current_cli, i)) break;
if (tries-- == 0) {
printf("pid %d failed to start\n", (int)getpid());
_exit(1);
@@ -4805,6 +5014,8 @@ static struct {
{"CHKPATH", torture_chkpath_test, 0},
{"FDSESS", run_fdsesstest, 0},
{ "EATEST", run_eatest, 0},
+ { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
+ { "LOCAL-GENCACHE", run_local_gencache, 0},
{NULL, NULL, 0}};
@@ -4884,6 +5095,7 @@ static void usage(void)
printf("\t-A showall\n");
printf("\t-p port\n");
printf("\t-s seed\n");
+ printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
printf("\n\n");
printf("tests are:");
@@ -4952,7 +5164,7 @@ static void usage(void)
fstrcpy(workgroup, lp_workgroup());
- while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Ac:ks:")) != EOF) {
+ while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Ac:ks:b:")) != EOF) {
switch (opt) {
case 'p':
port_to_use = atoi(optarg);
@@ -5008,6 +5220,10 @@ static void usage(void)
gotpass = 1;
}
break;
+ case 'b':
+ fstrcpy(multishare_conn_fname, optarg);
+ use_multishare_conn = True;
+ break;
default:
printf("Unknown option %c (%d)\n", (char)opt, opt);
usage();
diff --git a/source/torture/utable.c b/source/torture/utable.c
index 1d06194e46d..e5126da91d3 100644
--- a/source/torture/utable.c
+++ b/source/torture/utable.c
@@ -32,7 +32,7 @@ BOOL torture_utable(int dummy)
printf("starting utable\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
@@ -47,7 +47,7 @@ BOOL torture_utable(int dummy)
SSVAL(&c2, 0, c);
fstrcpy(fname, "\\utable\\x");
p = fname+strlen(fname);
- len = convert_string(CH_UCS2, CH_UNIX,
+ len = convert_string(CH_UTF16LE, CH_UNIX,
&c2, 2,
p, sizeof(fname)-strlen(fname), True);
p[len] = 0;
@@ -104,7 +104,7 @@ static char *form_name(int c)
p = fname+strlen(fname);
SSVAL(&c2, 0, c);
- len = convert_string(CH_UCS2, CH_UNIX,
+ len = convert_string(CH_UTF16LE, CH_UNIX,
&c2, 2,
p, sizeof(fname)-strlen(fname), True);
p[len] = 0;
@@ -121,7 +121,7 @@ BOOL torture_casetable(int dummy)
smb_ucs2_t equiv[0x10000][MAX_EQUIVALENCE];
printf("starting casetable\n");
- if (!torture_open_connection(&cli)) {
+ if (!torture_open_connection(&cli, 0)) {
return False;
}
diff --git a/source/torture/vfstest.c b/source/torture/vfstest.c
index 61bb4b0bf65..872c7a74c32 100644
--- a/source/torture/vfstest.c
+++ b/source/torture/vfstest.c
@@ -479,6 +479,27 @@ BOOL reload_services(BOOL test)
return (ret);
}
+struct event_context *smbd_event_context(void)
+{
+ static struct event_context *ctx;
+
+ if (!ctx && !(ctx = event_context_init(NULL))) {
+ smb_panic("Could not init smbd event context\n");
+ }
+ return ctx;
+}
+
+struct messaging_context *smbd_messaging_context(void)
+{
+ static struct messaging_context *ctx;
+
+ if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
+ smbd_event_context()))) {
+ smb_panic("Could not init smbd messaging context\n");
+ }
+ return ctx;
+}
+
/* Main function */
int main(int argc, char *argv[])
@@ -575,6 +596,6 @@ int main(int argc, char *argv[])
process_cmd(&vfs, line);
}
- free(vfs.conn);
+ conn_free(vfs.conn);
return 0;
}
diff --git a/source/utils/debug2html.c b/source/utils/debug2html.c
index bec4d81ae2b..6d1b2b25352 100644
--- a/source/utils/debug2html.c
+++ b/source/utils/debug2html.c
@@ -145,6 +145,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
case dbg_lineno:
(void)printf( ")" );
break;
+ default:
+ break;
}
switch( newtok )
@@ -158,6 +160,8 @@ static void newblock( dbg_Token old, dbg_Token newtok )
case dbg_lineno:
(void)printf( "(" );
break;
+ default:
+ break;
}
} /* newblock */
diff --git a/source/utils/debugparse.c b/source/utils/debugparse.c
index c5fe3e2ee85..9c86fcc37b1 100644
--- a/source/utils/debugparse.c
+++ b/source/utils/debugparse.c
@@ -245,6 +245,7 @@ dbg_Token dbg_char2token( dbg_Token *state, int c )
return( *state );
} /* dbg_char2token */
+void dbg_test( void );
void dbg_test( void )
/* ------------------------------------------------------------------------ **
* Simple test function.
diff --git a/source/utils/eventlogadm.c b/source/utils/eventlogadm.c
index 036ce3ad4b9..a964043c830 100644
--- a/source/utils/eventlogadm.c
+++ b/source/utils/eventlogadm.c
@@ -60,7 +60,7 @@ static void display_eventlog_names( void )
printf( "\t<None specified>\n");
}
-int DoAddSourceCommand( int argc, char **argv, BOOL debugflag, char *exename )
+static int DoAddSourceCommand( int argc, char **argv, BOOL debugflag, char *exename )
{
if ( argc < 3 ) {
@@ -79,7 +79,7 @@ int DoAddSourceCommand( int argc, char **argv, BOOL debugflag, char *exename )
return 0;
}
-int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
+static int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
{
FILE *f1;
char *argfname;
diff --git a/source/utils/log2pcaphex.c b/source/utils/log2pcaphex.c
index 24412cbe85e..b7a595f7544 100644
--- a/source/utils/log2pcaphex.c
+++ b/source/utils/log2pcaphex.c
@@ -96,7 +96,7 @@ typedef struct {
static hdr_tcp_t HDR_TCP = {139, 139, 0, 0, 0x50, 0, 0, 0, 0};
-void print_pcap_header(FILE *out)
+static void print_pcap_header(FILE *out)
{
struct tcpdump_file_header h;
h.magic = TCPDUMP_MAGIC;
@@ -109,7 +109,7 @@ void print_pcap_header(FILE *out)
fwrite(&h, sizeof(struct tcpdump_file_header), 1, out);
}
-void print_pcap_packet(FILE *out, unsigned char *data, long length, long caplen)
+static void print_pcap_packet(FILE *out, unsigned char *data, long length, long caplen)
{
static int i = 0;
struct tcpdump_packet p;
@@ -122,7 +122,7 @@ void print_pcap_packet(FILE *out, unsigned char *data, long length, long caplen)
fwrite(data, sizeof(unsigned char), caplen, out);
}
-void print_hex_packet(FILE *out, unsigned char *data, long length)
+static void print_hex_packet(FILE *out, unsigned char *data, long length)
{
long i,cur = 0;
while(cur < length) {
@@ -136,13 +136,13 @@ void print_hex_packet(FILE *out, unsigned char *data, long length)
}
}
-void print_netbios_packet(FILE *out, unsigned char *data, long length, long actual_length)
+static void print_netbios_packet(FILE *out, unsigned char *data, long length, long actual_length)
{
unsigned char *newdata; long offset = 0;
long newlen;
newlen = length+sizeof(HDR_IP)+sizeof(HDR_TCP);
- newdata = malloc(newlen);
+ newdata = (unsigned char *)malloc(newlen);
HDR_IP.packet_length = htons(newlen);
HDR_TCP.window = htons(0x2000);
@@ -159,13 +159,13 @@ void print_netbios_packet(FILE *out, unsigned char *data, long length, long actu
unsigned char *curpacket = NULL;
long curpacket_len = 0;
-void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *data_offset, long *data_length)
+static void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *data_offset, long *data_length)
{
unsigned char *buffer;
int tmp; long i;
assert(fscanf(in, " size=%ld\n", buffersize));
*buffersize+=4; /* for netbios */
- buffer = malloc(*buffersize);
+ buffer = (unsigned char *)malloc(*buffersize);
memset(buffer, 0, *buffersize);
/* NetBIOS */
buffer[0] = 0x00;
@@ -197,7 +197,7 @@ void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *dat
*_buffer = buffer;
}
-long read_log_data(FILE *in, unsigned char *buffer, long data_length)
+static long read_log_data(FILE *in, unsigned char *buffer, long data_length)
{
long i, addr; char real[2][16]; int ret;
unsigned int tmp;
diff --git a/source/utils/net.c b/source/utils/net.c
index bef2a0a83c2..7b97476a25e 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -77,6 +77,7 @@ const char *opt_target_workgroup = NULL;
int opt_machine_pass = 0;
BOOL opt_localgroup = False;
BOOL opt_domaingroup = False;
+static BOOL do_talloc_report=False;
const char *opt_newntname = "";
int opt_rid = 0;
int opt_acls = 0;
@@ -159,6 +160,7 @@ int net_run_function2(int argc, const char **argv, const char *whoami,
/****************************************************************************
connect to \\server\service
****************************************************************************/
+
NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
const char *server_name,
const char *service_name,
@@ -172,13 +174,13 @@ NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
opt_password = SMB_STRDUP(pass);
}
}
-
+
nt_status = cli_full_connection(c, NULL, server_name,
server_ip, opt_port,
service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
-
+
if (NT_STATUS_IS_OK(nt_status)) {
return nt_status;
} else {
@@ -235,20 +237,57 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
/****************************************************************************
+ Return malloced user@realm for krb5 login.
+****************************************************************************/
+
+static char *get_user_and_realm(const char *username)
+{
+ char *user_and_realm = NULL;
+
+ if (!username) {
+ return NULL;
+ }
+ if (strchr_m(username, '@')) {
+ user_and_realm = SMB_STRDUP(username);
+ } else {
+ if (asprintf(&user_and_realm, "%s@%s", username, lp_realm()) == -1) {
+ user_and_realm = NULL;
+ }
+ }
+ return user_and_realm;
+}
+
+/****************************************************************************
connect to \\server\ipc$ using KRB5
****************************************************************************/
+
NTSTATUS connect_to_ipc_krb5(struct cli_state **c,
struct in_addr *server_ip, const char *server_name)
{
NTSTATUS nt_status;
+ char *user_and_realm = NULL;
+
+ if (!opt_password && !opt_machine_pass) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ opt_password = SMB_STRDUP(pass);
+ }
+ }
+
+ user_and_realm = get_user_and_realm(opt_user_name);
+ if (!user_and_realm) {
+ return NT_STATUS_NO_MEMORY;
+ }
nt_status = cli_full_connection(c, NULL, server_name,
server_ip, opt_port,
"IPC$", "IPC",
- opt_user_name, opt_workgroup,
+ user_and_realm, opt_workgroup,
opt_password, CLI_FULL_CONNECTION_USE_KERBEROS,
Undefined, NULL);
+ SAFE_FREE(user_and_realm);
+
if (NT_STATUS_IS_OK(nt_status)) {
return nt_status;
} else {
@@ -480,7 +519,7 @@ static int net_group(int argc, const char **argv)
static int net_join(int argc, const char **argv)
{
- if (net_ads_check() == 0) {
+ if (net_ads_check_our_domain() == 0) {
if (net_ads_join(argc, argv) == 0)
return 0;
else
@@ -491,7 +530,7 @@ static int net_join(int argc, const char **argv)
static int net_changetrustpw(int argc, const char **argv)
{
- if (net_ads_check() == 0)
+ if (net_ads_check_our_domain() == 0)
return net_ads_changetrustpw(argc, argv);
return net_rpc_changetrustpw(argc, argv);
@@ -513,7 +552,7 @@ static int net_changesecretpw(int argc, const char **argv)
set_line_buffering(stdout);
set_line_buffering(stderr);
}
-
+
trust_pw = get_pass("Enter machine password: ", opt_stdin);
if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) {
@@ -884,6 +923,7 @@ static struct functable net_func[] = {
{"timestamps", 0, POPT_ARG_NONE, &opt_timestamps},
{"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
{"destination", 0, POPT_ARG_STRING, &opt_destination},
+ {"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report},
POPT_COMMON_SAMBA
{ 0, 0, 0, 0}
@@ -947,6 +987,10 @@ static struct functable net_func[] = {
}
}
+ if (do_talloc_report) {
+ talloc_enable_leak_report();
+ }
+
if (opt_requester_name) {
set_global_myname(opt_requester_name);
}
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index fcf1bf25083..02a0b68932c 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -55,6 +55,9 @@ int net_ads_usage(int argc, const char **argv)
d_printf(" Issue LDAP search queries using a general filter, by DN, or by SID\n");
d_printf("keytab\n");
d_printf(" Manage a local keytab file based on the machine account in AD\n");
+ d_printf("dns\n");
+ d_printf(" Issue a dynamic DNS update request the server's hostname\n");
+ d_printf(" (using the machine credentials)\n");
return -1;
}
@@ -132,8 +135,8 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk);
if (*reply.user_name) printf("User name:\t%s\n", reply.user_name);
- printf("Site Name:\t\t%s\n", reply.site_name);
- printf("Site Name (2):\t\t%s\n", reply.site_name_2);
+ printf("Server Site Name :\t\t%s\n", reply.server_site_name);
+ printf("Client Site Name :\t\t%s\n", reply.client_site_name);
d_printf("NT Version: %d\n", reply.version);
d_printf("LMNT Token: %.2x\n", reply.lmnt_token);
@@ -150,20 +153,12 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
static int net_ads_lookup(int argc, const char **argv)
{
ADS_STRUCT *ads;
- ADS_STATUS status;
- const char *realm = assume_own_realm();
-
- ads = ads_init(realm, opt_target_workgroup, opt_host);
- if (ads) {
- ads->auth.flags |= ADS_AUTH_NO_BIND;
- }
- status = ads_connect(ads);
- if (!ADS_ERR_OK(status) || !ads) {
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
d_fprintf(stderr, "Didn't find the cldap server!\n");
return -1;
}
-
+
if (!ads->config.realm) {
ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
ads->ldap_port = 389;
@@ -177,14 +172,12 @@ static int net_ads_lookup(int argc, const char **argv)
static int net_ads_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
- const char *realm = assume_own_realm();
- if ( (ads = ads_init(realm, opt_target_workgroup, opt_host)) != NULL ) {
- ads->auth.flags |= ADS_AUTH_NO_BIND;
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
+ d_fprintf(stderr, "Didn't find the ldap server!\n");
+ return -1;
}
- ads_connect(ads);
-
if (!ads || !ads->config.realm) {
d_fprintf(stderr, "Didn't find the ldap server!\n");
return -1;
@@ -216,24 +209,30 @@ static void use_in_memory_ccache(void) {
setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
}
-static ADS_STRUCT *ads_startup(BOOL only_own_domain)
+static ADS_STATUS ads_startup_int(BOOL only_own_domain, uint32 auth_flags, ADS_STRUCT **ads_ret)
{
- ADS_STRUCT *ads;
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
BOOL need_password = False;
BOOL second_time = False;
char *cp;
const char *realm = NULL;
-
+ BOOL tried_closest_dc = False;
+
/* lp_realm() should be handled by a command line param,
However, the join requires that realm be set in smb.conf
and compares our realm with the remote server's so this is
ok until someone needs more flexibility */
+ *ads_ret = NULL;
+
+retry_connect:
if (only_own_domain) {
realm = lp_realm();
+ } else {
+ realm = assume_own_realm();
}
-
+
ads = ads_init(realm, opt_target_workgroup, opt_host);
if (!opt_user_name) {
@@ -246,17 +245,24 @@ static ADS_STRUCT *ads_startup(BOOL only_own_domain)
retry:
if (!opt_password && need_password && !opt_machine_pass) {
- char *prompt;
+ char *prompt = NULL;
asprintf(&prompt,"%s's password: ", opt_user_name);
+ if (!prompt) {
+ ads_destroy(&ads);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
opt_password = getpass(prompt);
free(prompt);
}
if (opt_password) {
use_in_memory_ccache();
+ SAFE_FREE(ads->auth.password);
ads->auth.password = smb_xstrdup(opt_password);
}
+ ads->auth.flags |= auth_flags;
+ SAFE_FREE(ads->auth.user_name);
ads->auth.user_name = smb_xstrdup(opt_user_name);
/*
@@ -265,9 +271,10 @@ retry:
* This is only used to establish the connection.
*/
if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
- *cp++ = '\0';
- ads->auth.realm = smb_xstrdup(cp);
- strupper_m(ads->auth.realm);
+ *cp++ = '\0';
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = smb_xstrdup(cp);
+ strupper_m(ads->auth.realm);
}
status = ads_connect(ads);
@@ -278,22 +285,52 @@ retry:
NT_STATUS_NO_LOGON_SERVERS)) {
DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
ads_destroy(&ads);
- return NULL;
+ return status;
}
- if (!need_password && !second_time) {
+ if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
need_password = True;
second_time = True;
goto retry;
} else {
- DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
ads_destroy(&ads);
- return NULL;
+ return status;
+ }
+ }
+
+ /* when contacting our own domain, make sure we use the closest DC.
+ * This is done by reconnecting to ADS because only the first call to
+ * ads_connect will give us our own sitename */
+
+ if ((only_own_domain || !opt_host) && !tried_closest_dc) {
+
+ tried_closest_dc = True; /* avoid loop */
+
+ if (!ads->config.tried_closest_dc) {
+
+ namecache_delete(ads->server.realm, 0x1C);
+ namecache_delete(ads->server.workgroup, 0x1C);
+
+ ads_destroy(&ads);
+ ads = NULL;
+
+ goto retry_connect;
}
}
- return ads;
+
+ *ads_ret = ads;
+ return status;
}
+ADS_STATUS ads_startup(BOOL only_own_domain, ADS_STRUCT **ads)
+{
+ return ads_startup_int(only_own_domain, 0, ads);
+}
+
+ADS_STATUS ads_startup_nobind(BOOL only_own_domain, ADS_STRUCT **ads)
+{
+ return ads_startup_int(only_own_domain, ADS_AUTH_NO_BIND, ads);
+}
/*
Check to see if connection can be made via ads.
@@ -335,17 +372,9 @@ int net_ads_check(void)
static int net_ads_workgroup(int argc, const char **argv)
{
ADS_STRUCT *ads;
- ADS_STATUS status;
- const char *realm = assume_own_realm();
struct cldap_netlogon_reply reply;
- ads = ads_init(realm, opt_target_workgroup, opt_host);
- if (ads) {
- ads->auth.flags |= ADS_AUTH_NO_BIND;
- }
-
- status = ads_connect(ads);
- if (!ADS_ERR_OK(status) || !ads) {
+ if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
d_fprintf(stderr, "Didn't find the cldap server!\n");
return -1;
}
@@ -407,13 +436,13 @@ static int ads_user_add(int argc, const char **argv)
ADS_STRUCT *ads;
ADS_STATUS status;
char *upn, *userdn;
- void *res=NULL;
+ LDAPMessage *res=NULL;
int rc = -1;
char *ou_str = NULL;
if (argc < 1) return net_ads_user_usage(argc, argv);
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -484,7 +513,7 @@ static int ads_user_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res;
+ LDAPMessage *res;
const char *attrs[] = {"memberOf", NULL};
char *searchstring=NULL;
char **grouplist;
@@ -501,7 +530,7 @@ static int ads_user_info(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
SAFE_FREE(escaped_user);
return -1;
}
@@ -541,20 +570,20 @@ static int ads_user_delete(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *userdn;
if (argc < 1) {
return net_ads_user_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
rc = ads_find_user_acct(ads, &res, argv[0]);
if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
- DEBUG(0, ("User %s does not exist\n", argv[0]));
+ d_printf("User %s does not exist.\n", argv[0]);
ads_msgfree(ads, res);
ads_destroy(&ads);
return -1;
@@ -589,7 +618,7 @@ int net_ads_user(int argc, const char **argv)
char *disp_fields[2] = {NULL, NULL};
if (argc == 0) {
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -619,7 +648,7 @@ static int ads_group_add(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
- void *res=NULL;
+ LDAPMessage *res=NULL;
int rc = -1;
char *ou_str = NULL;
@@ -627,7 +656,7 @@ static int ads_group_add(int argc, const char **argv)
return net_ads_group_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -671,20 +700,20 @@ static int ads_group_delete(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
char *groupdn;
if (argc < 1) {
return net_ads_group_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
rc = ads_find_user_acct(ads, &res, argv[0]);
if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
- DEBUG(0, ("Group %s does not exist\n", argv[0]));
+ d_printf("Group %s does not exist.\n", argv[0]);
ads_msgfree(ads, res);
ads_destroy(&ads);
return -1;
@@ -718,7 +747,7 @@ int net_ads_group(int argc, const char **argv)
char *disp_fields[2] = {NULL, NULL};
if (argc == 0) {
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -742,9 +771,9 @@ static int net_ads_status(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res;
+ LDAPMessage *res;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -772,13 +801,17 @@ static int net_ads_status(int argc, const char **argv)
That only worked using the machine creds because added the machine
with full control to the computer object's ACL.
*******************************************************************/
+
static int net_ads_leave(int argc, const char **argv)
{
ADS_STRUCT *ads = NULL;
+ ADS_STATUS adsret;
+ NTSTATUS status;
int ret = -1;
struct cli_state *cli = NULL;
TALLOC_CTX *ctx;
DOM_SID *dom_sid = NULL;
+ char *short_domain_name = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
@@ -786,14 +819,14 @@ static int net_ads_leave(int argc, const char **argv)
}
if (!(ctx = talloc_init("net_ads_leave"))) {
- DEBUG(0, ("Could not initialise talloc context\n"));
+ d_fprintf(stderr, "Could not initialise talloc context.\n");
return -1;
}
/* The finds a DC and takes care of getting the
user creds if necessary */
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -805,24 +838,35 @@ static int net_ads_leave(int argc, const char **argv)
goto done;
}
- saf_store( cli->server_domain, cli->desthost );
-
- if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &dom_sid )) ) {
+ if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &short_domain_name, &dom_sid )) ) {
goto done;
}
- if ( !NT_STATUS_IS_OK(netdom_leave_domain( ctx, cli, dom_sid )) ) {
- d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
+ saf_delete( short_domain_name );
+
+ status = netdom_leave_domain(ctx, cli, dom_sid);
+
+ /* Try and delete it via LDAP - the old way we used to. */
+
+ adsret = ads_leave_realm(ads, global_myname());
+ if (ADS_ERR_OK(adsret)) {
+ d_printf("Deleted account for '%s' in realm '%s'\n",
global_myname(), ads->config.realm);
- goto done;
+ ret = 0;
+ } else {
+ /* We couldn't delete it - see if the disable succeeded. */
+ if (NT_STATUS_IS_OK(status)) {
+ d_printf("Disabled account for '%s' in realm '%s'\n",
+ global_myname(), ads->config.realm);
+ ret = 0;
+ } else {
+ d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
+ global_myname(), ads->config.realm);
+ }
}
-
- d_printf("Disabled account for '%s' in realm '%s'\n",
- global_myname(), ads->config.realm);
-
- ret = 0;
done:
+
if ( cli )
cli_shutdown(cli);
@@ -832,23 +876,25 @@ done:
return ret;
}
-static int net_ads_join_ok(void)
+static NTSTATUS net_ads_join_ok(void)
{
ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return -1;
+ return NT_STATUS_ACCESS_DENIED;
}
net_use_machine_password();
- if (!(ads = ads_startup(True))) {
- return -1;
+ status = ads_startup(True, &ads);
+ if (!ADS_ERR_OK(status)) {
+ return ads_ntstatus(status);
}
ads_destroy(&ads);
- return 0;
+ return NT_STATUS_OK;
}
/*
@@ -856,11 +902,14 @@ static int net_ads_join_ok(void)
*/
int net_ads_testjoin(int argc, const char **argv)
{
+ NTSTATUS status;
use_in_memory_ccache();
/* Display success or failure */
- if (net_ads_join_ok() != 0) {
- fprintf(stderr,"Join to domain is not valid\n");
+ status = net_ads_join_ok();
+ if (!NT_STATUS_IS_OK(status)) {
+ fprintf(stderr,"Join to domain is not valid: %s\n",
+ get_friendly_nt_error_msg(status));
return -1;
}
@@ -872,59 +921,63 @@ int net_ads_testjoin(int argc, const char **argv)
Simple configu checks before beginning the join
********************************************************************/
-static int check_ads_config( void )
+static NTSTATUS check_ads_config( void )
{
if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
d_printf("Host is not configured as a member server.\n");
- return -1;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
}
if (strlen(global_myname()) > 15) {
d_printf("Our netbios name can be at most 15 chars long, "
- "\"%s\" is %u chars long\n",
- global_myname(), (unsigned int)strlen(global_myname()));
- return -1;
+ "\"%s\" is %u chars long\n", global_myname(),
+ (unsigned int)strlen(global_myname()));
+ return NT_STATUS_NAME_TOO_LONG;
}
if ( lp_security() == SEC_ADS && !*lp_realm()) {
- d_fprintf(stderr, "realm must be set in in smb.conf for ADS "
- "join to succeed.\n");
- return -1;
+ d_fprintf(stderr, "realm must be set in in %s for ADS "
+ "join to succeed.\n", dyn_CONFIGFILE);
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return -1;
+ /* This is a good bet for failure of secrets_init ... */
+ return NT_STATUS_ACCESS_DENIED;
}
- return 0;
+ return NT_STATUS_OK;
}
/*******************************************************************
Do the domain join
********************************************************************/
-static int net_join_domain( TALLOC_CTX *ctx, const char *servername,
- struct in_addr *ip, DOM_SID **dom_sid, const char *password )
+static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername,
+ struct in_addr *ip, char **domain,
+ DOM_SID **dom_sid,
+ const char *password)
{
- int ret = -1;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct cli_state *cli = NULL;
- if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, ip, servername)) )
+ ret = connect_to_ipc_krb5(&cli, ip, servername);
+ if ( !NT_STATUS_IS_OK(ret) ) {
goto done;
+ }
- saf_store( cli->server_domain, cli->desthost );
-
- if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, dom_sid )) )
- goto done;
-
- if ( !NT_STATUS_IS_OK(netdom_join_domain( ctx, cli, *dom_sid,
- password, ND_TYPE_AD )) )
- {
+ ret = netdom_get_domain_sid( ctx, cli, domain, dom_sid );
+ if ( !NT_STATUS_IS_OK(ret) ) {
goto done;
}
-
- ret = 0;
+
+ /* cli->server_domain is not filled in when using krb5
+ session setups */
+
+ saf_store( *domain, cli->desthost );
+
+ ret = netdom_join_domain( ctx, cli, *dom_sid, password, ND_TYPE_AD );
done:
if ( cli )
@@ -956,7 +1009,7 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
/* Find our DN */
- status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
if (!ADS_ERR_OK(status))
return status;
@@ -1026,7 +1079,7 @@ static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const
/* Find our DN */
- status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
if (!ADS_ERR_OK(status))
return status;
@@ -1080,7 +1133,7 @@ static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
return ADS_ERROR(LDAP_NO_MEMORY);
}
- rc = ads_search_dn(ads, (void**)&res, dn, NULL);
+ rc = ads_search_dn(ads, &res, dn, NULL);
ads_msgfree(ads, res);
if (ADS_ERR_OK(rc)) {
@@ -1120,7 +1173,7 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
/* go ahead and setup the default salt */
if ( (std_salt = kerberos_standard_des_salt()) == NULL ) {
- DEBUG(0,("net_derive_salting_principal: failed to obtain stanard DES salt\n"));
+ d_fprintf(stderr, "net_derive_salting_principal: failed to obtain stanard DES salt\n");
return False;
}
@@ -1133,7 +1186,7 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
char *upn;
int count;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ status = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(status)) {
return False;
}
@@ -1154,7 +1207,135 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
return kerberos_secrets_store_des_salt( salt );
}
-/*********************************************************
+/*******************************************************************
+ Send a DNS update request
+*******************************************************************/
+
+#if defined(WITH_DNS_UPDATES)
+#include "dns.h"
+DNS_ERROR DoDNSUpdate(char *pszServerName,
+ const char *pszDomainName,
+ const char *pszHostName,
+ const struct in_addr *iplist, int num_addrs );
+
+
+static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
+ const char *machine_name,
+ const struct in_addr *addrs,
+ int num_addrs)
+{
+ struct dns_rr_ns *nameservers = NULL;
+ int ns_count = 0;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ DNS_ERROR dns_err;
+ fstring dns_server;
+ const char *dnsdomain = NULL;
+ char *root_domain = NULL;
+
+ if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
+ d_printf("No DNS domain configured for %s. "
+ "Unable to perform DNS Update.\n", machine_name);
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ dnsdomain++;
+
+ status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
+ if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+ /* Child domains often do not have NS records. Look
+ for the NS record for the forest root domain
+ (rootDomainNamingContext in therootDSE) */
+
+ const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
+ LDAPMessage *msg = NULL;
+ char *root_dn;
+ ADS_STATUS ads_status;
+
+ if ( !ads->ld ) {
+ ads_status = ads_connect( ads );
+ if ( !ADS_ERR_OK(ads_status) ) {
+ DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
+ goto done;
+ }
+ }
+
+ ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
+ "(objectclass=*)", rootname_attrs, &msg);
+ if (!ADS_ERR_OK(ads_status)) {
+ goto done;
+ }
+
+ root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
+ if ( !root_dn ) {
+ ads_msgfree( ads, msg );
+ goto done;
+ }
+
+ root_domain = ads_build_domain( root_dn );
+
+ /* cleanup */
+ ads_msgfree( ads, msg );
+
+ /* try again for NS servers */
+
+ status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
+
+ if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+ DEBUG(3,("net_ads_join: Failed to find name server for the %s "
+ "realm\n", ads->config.realm));
+ goto done;
+ }
+
+ dnsdomain = root_domain;
+
+ }
+
+ /* Now perform the dns update - we'll try non-secure and if we fail,
+ we'll follow it up with a secure update */
+
+ fstrcpy( dns_server, nameservers[0].hostname );
+
+ dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ if (!ERR_DNS_IS_OK(dns_err)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ }
+
+done:
+
+ SAFE_FREE( root_domain );
+
+ return status;
+}
+
+static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
+{
+ int num_addrs;
+ struct in_addr *iplist = NULL;
+ fstring machine_name;
+ NTSTATUS status;
+
+ name_to_fqdn( machine_name, global_myname() );
+ strlower_m( machine_name );
+
+ /* Get our ip address (not the 127.0.0.x address but a real ip
+ * address) */
+
+ num_addrs = get_my_ip_address( &iplist );
+ if ( num_addrs <= 0 ) {
+ DEBUG(4,("net_ads_join: Failed to find my non-loopback IP "
+ "addresses!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = net_update_dns_internal(mem_ctx, ads, machine_name,
+ iplist, num_addrs);
+ SAFE_FREE( iplist );
+ return status;
+}
+#endif
+
+
+/*******************************************************************
utility function to parse an integer parameter from
"parameter = value"
**********************************************************/
@@ -1180,6 +1361,8 @@ static int net_ads_join_usage(int argc, const char **argv)
d_printf(" createcomputer=OU Precreate the computer account in a specific OU.\n");
d_printf(" The OU string read from top to bottom without RDNs and delimited by a '/'.\n");
d_printf(" E.g. \"createcomputer=Computers/Servers/Unix\"\n");
+ d_printf(" NB: A backslash '\\' is used as escape at multiple levels and may\n");
+ d_printf(" need to be doubled or even quadrupled. It is not used as a separator");
return -1;
}
@@ -1191,35 +1374,47 @@ int net_ads_join(int argc, const char **argv)
{
ADS_STRUCT *ads = NULL;
ADS_STATUS status;
+ NTSTATUS nt_status;
char *machine_account = NULL;
- const char *short_domain_name = NULL;
+ char *short_domain_name = NULL;
char *tmp_password, *password;
- struct cldap_netlogon_reply cldap_reply;
- TALLOC_CTX *ctx;
+ TALLOC_CTX *ctx = NULL;
DOM_SID *domain_sid = NULL;
BOOL createupn = False;
const char *machineupn = NULL;
const char *create_in_ou = NULL;
int i;
+ fstring dc_name;
+ struct in_addr dcip;
- if ( check_ads_config() != 0 ) {
+ nt_status = check_ads_config();
+ if (!NT_STATUS_IS_OK(nt_status)) {
d_fprintf(stderr, "Invalid configuration. Exiting....\n");
goto fail;
}
- if ( (ads = ads_startup(True)) == NULL ) {
+ /* find a DC to initialize the server affinity cache */
+
+ get_dc_name( lp_workgroup(), lp_realm(), dc_name, &dcip );
+
+ status = ads_startup(True, &ads);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ nt_status = ads_ntstatus(status);
goto fail;
}
if (strcmp(ads->config.realm, lp_realm()) != 0) {
- d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf "
+ d_fprintf(stderr, "realm of remote server (%s) and realm in %s "
"(%s) DO NOT match. Aborting join\n", ads->config.realm,
- lp_realm());
+ dyn_CONFIGFILE, lp_realm());
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
if (!(ctx = talloc_init("net_ads_join"))) {
- DEBUG(0, ("Could not initialise talloc context\n"));
+ d_fprintf(stderr, "Could not initialise talloc context.\n");
+ nt_status = NT_STATUS_NO_MEMORY;
goto fail;
}
@@ -1233,11 +1428,13 @@ int net_ads_join(int argc, const char **argv)
else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
d_fprintf(stderr, "Please supply a valid OU path\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
else {
d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
@@ -1250,6 +1447,9 @@ int net_ads_join(int argc, const char **argv)
if ( !ADS_ERR_OK(status) ) {
d_fprintf( stderr, "Failed to pre-create the machine object "
"in OU %s.\n", argv[0]);
+ DEBUG(1, ("error calling net_precreate_machine_acct: %s\n",
+ ads_errstr(status)));
+ nt_status = ads_ntstatus(status);
goto fail;
}
}
@@ -1259,27 +1459,22 @@ int net_ads_join(int argc, const char **argv)
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
password = talloc_strdup(ctx, tmp_password);
- if ( net_join_domain( ctx, ads->config.ldap_server_name, &ads->ldap_ip, &domain_sid, password ) != 0 ) {
- d_fprintf(stderr, "Failed to join domain!\n");
+ nt_status = net_join_domain(ctx, ads->config.ldap_server_name,
+ &ads->ldap_ip, &short_domain_name, &domain_sid, password);
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ DEBUG(1, ("call of net_join_domain failed: %s\n",
+ get_friendly_nt_error_msg(nt_status)));
goto fail;
}
-
+
/* Check the short name of the domain */
- ZERO_STRUCT( cldap_reply );
-
- if ( ads_cldap_netlogon( ads->config.ldap_server_name,
- ads->server.realm, &cldap_reply ) )
- {
- short_domain_name = talloc_strdup( ctx, cldap_reply.netbios_domain );
- if ( !strequal(lp_workgroup(), short_domain_name) ) {
- d_printf("The workgroup in smb.conf does not match the short\n");
- d_printf("domain name obtained from the server.\n");
- d_printf("Using the name [%s] from the server.\n", short_domain_name);
- d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
- }
- } else {
- short_domain_name = lp_workgroup();
+ if ( !strequal(lp_workgroup(), short_domain_name) ) {
+ d_printf("The workgroup in %s does not match the short\n", dyn_CONFIGFILE);
+ d_printf("domain name obtained from the server.\n");
+ d_printf("Using the name [%s] from the server.\n", short_domain_name);
+ d_printf("You should set \"workgroup = %s\" in %s.\n",
+ short_domain_name, dyn_CONFIGFILE);
}
d_printf("Using short domain name -- %s\n", short_domain_name);
@@ -1292,6 +1487,9 @@ int net_ads_join(int argc, const char **argv)
if ( (netdom_store_machine_account( lp_workgroup(), domain_sid, password ) == -1)
|| (netdom_store_machine_account( short_domain_name, domain_sid, password ) == -1) )
{
+ /* issue an internal error here for now.
+ * everything else would mean changing tdb routines. */
+ nt_status = NT_STATUS_INTERNAL_ERROR;
goto fail;
}
@@ -1323,6 +1521,7 @@ int net_ads_join(int argc, const char **argv)
netdom_store_machine_account( lp_workgroup(), domain_sid, "" );
netdom_store_machine_account( short_domain_name, domain_sid, "" );
+ nt_status = ads_ntstatus(status);
goto fail;
}
@@ -1352,7 +1551,31 @@ int net_ads_join(int argc, const char **argv)
DEBUG(1,("Error creating host keytab!\n"));
}
- d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
+#if defined(WITH_DNS_UPDATES)
+ /* We enter this block with user creds */
+ ads_kdestroy( NULL );
+ ads_destroy(&ads);
+ ads = NULL;
+
+ if ( (ads = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
+ /* kinit with the machine password */
+
+ use_in_memory_ccache();
+ asprintf( &ads->auth.user_name, "%s$", global_myname() );
+ ads->auth.password = secrets_fetch_machine_password(
+ lp_workgroup(), NULL, NULL );
+ ads->auth.realm = SMB_STRDUP( lp_realm() );
+ ads_kinit_password( ads );
+ }
+
+ if ( !ads || !NT_STATUS_IS_OK(net_update_dns( ctx, ads )) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ }
+
+ /* exit from this block using machine creds */
+#endif
+
+ d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->server.realm);
SAFE_FREE(machine_account);
TALLOC_FREE( ctx );
@@ -1361,8 +1584,119 @@ int net_ads_join(int argc, const char **argv)
return 0;
fail:
+ /* issue an overall failure message at the end. */
+ d_printf("Failed to join domain: %s\n", get_friendly_nt_error_msg(nt_status));
+
+ SAFE_FREE(machine_account);
+ TALLOC_FREE( ctx );
+ ads_destroy(&ads);
+
+ return -1;
+
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns_usage(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ d_printf("net ads dns <command>\n");
+ d_printf("Valid commands:\n");
+ d_printf(" register Issue a dynamic DNS update request for our hostname\n");
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
+ return -1;
+#endif
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns_register(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ TALLOC_CTX *ctx;
+
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc > 0) {
+ d_fprintf(stderr, "net ads dns register <name> <ip>\n");
+ return -1;
+ }
+
+ if (!(ctx = talloc_init("net_ads_dns"))) {
+ d_fprintf(stderr, "Could not initialise talloc context\n");
+ return -1;
+ }
+
+ status = ads_startup(True, &ads);
+ if ( !ADS_ERR_OK(status) ) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ TALLOC_FREE(ctx);
+ return -1;
+ }
+
+ if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ ads_destroy( &ads );
+ TALLOC_FREE( ctx );
+ return -1;
+ }
+
+ d_fprintf( stderr, "Successfully registered hostname with DNS\n" );
+
ads_destroy(&ads);
+ TALLOC_FREE( ctx );
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
return -1;
+#endif
+}
+
+#if defined(WITH_DNS_UPDATES)
+DNS_ERROR do_gethostbyname(const char *server, const char *host);
+#endif
+
+static int net_ads_dns_gethostbyname(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ DNS_ERROR err;
+
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc != 2) {
+ d_fprintf(stderr, "net ads dns gethostbyname <server> "
+ "<name>\n");
+ return -1;
+ }
+
+ err = do_gethostbyname(argv[0], argv[1]);
+
+ d_printf("do_gethostbyname returned %d\n", ERROR_DNS_V(err));
+#endif
+ return 0;
+}
+
+static int net_ads_dns(int argc, const char *argv[])
+{
+ struct functable func[] = {
+ {"REGISTER", net_ads_dns_register},
+ {"GETHOSTBYNAME", net_ads_dns_gethostbyname},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_dns_usage);
}
/*******************************************************************
@@ -1392,9 +1726,9 @@ static int net_ads_printer_search(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS rc;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1425,9 +1759,9 @@ static int net_ads_printer_info(int argc, const char **argv)
ADS_STRUCT *ads;
ADS_STATUS rc;
const char *servername, *printername;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1468,7 +1802,7 @@ static int net_ads_printer_info(int argc, const char **argv)
}
void do_drv_upgrade_printer(int msg_type, struct process_id src,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
return;
}
@@ -1485,9 +1819,9 @@ static int net_ads_printer_publish(int argc, const char **argv)
TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
ADS_MODLIST mods = ads_init_mods(mem_ctx);
char *prt_dn, *srv_dn, **srv_cn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -1571,9 +1905,9 @@ static int net_ads_printer_remove(int argc, const char **argv)
ADS_STATUS rc;
const char *servername;
char *prt_dn;
- void *res = NULL;
+ LDAPMessage *res = NULL;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -1720,7 +2054,7 @@ int net_ads_changetrustpw(int argc, const char **argv)
use_in_memory_ccache();
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
@@ -1779,13 +2113,13 @@ static int net_ads_search(int argc, const char **argv)
ADS_STATUS rc;
const char *ldap_exp;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
if (argc < 1) {
return net_ads_search_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1839,13 +2173,13 @@ static int net_ads_dn(int argc, const char **argv)
ADS_STATUS rc;
const char *dn;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
if (argc < 1) {
return net_ads_dn_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1898,14 +2232,14 @@ static int net_ads_sid(int argc, const char **argv)
ADS_STATUS rc;
const char *sid_string;
const char **attrs;
- void *res = NULL;
+ LDAPMessage *res = NULL;
DOM_SID sid;
if (argc < 1) {
return net_ads_sid_usage(argc, argv);
}
- if (!(ads = ads_startup(False))) {
+ if (!ADS_ERR_OK(ads_startup(False, &ads))) {
return -1;
}
@@ -1962,7 +2296,7 @@ static int net_ads_keytab_flush(int argc, const char **argv)
int ret;
ADS_STRUCT *ads;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
ret = ads_keytab_flush(ads);
@@ -1977,7 +2311,7 @@ static int net_ads_keytab_add(int argc, const char **argv)
ADS_STRUCT *ads;
d_printf("Processing principals to add...\n");
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
for (i = 0; i < argc; i++) {
@@ -1992,7 +2326,7 @@ static int net_ads_keytab_create(int argc, const char **argv)
ADS_STRUCT *ads;
int ret;
- if (!(ads = ads_startup(True))) {
+ if (!ADS_ERR_OK(ads_startup(True, &ads))) {
return -1;
}
ret = ads_keytab_create_default(ads);
@@ -2027,6 +2361,7 @@ int net_ads_help(int argc, const char **argv)
{"SEARCH", net_ads_search_usage},
{"INFO", net_ads_info},
{"JOIN", net_ads_join_usage},
+ {"DNS", net_ads_dns_usage},
{"LEAVE", net_ads_leave},
{"STATUS", net_ads_status},
{"PASSWORD", net_ads_password},
@@ -2047,6 +2382,7 @@ int net_ads(int argc, const char **argv)
{"STATUS", net_ads_status},
{"USER", net_ads_user},
{"GROUP", net_ads_group},
+ {"DNS", net_ads_dns},
{"PASSWORD", net_ads_password},
{"CHANGETRUSTPW", net_ads_changetrustpw},
{"PRINTER", net_ads_printer},
@@ -2056,6 +2392,7 @@ int net_ads(int argc, const char **argv)
{"WORKGROUP", net_ads_workgroup},
{"LOOKUP", net_ads_lookup},
{"KEYTAB", net_ads_keytab},
+ {"GPO", net_ads_gpo},
{"HELP", net_ads_help},
{NULL, NULL}
};
diff --git a/source/utils/net_ads_gpo.c b/source/utils/net_ads_gpo.c
index fec6fb88fa2..1865aee3d41 100644
--- a/source/utils/net_ads_gpo.c
+++ b/source/utils/net_ads_gpo.c
@@ -29,9 +29,9 @@ static int net_ads_gpo_usage(int argc, const char **argv)
"net ads gpo <COMMAND>\n"\
"<COMMAND> can be either:\n"\
" ADDLINK Link a container to a GPO\n"\
-" APPLY Apply all GPOs\n"\
-" DELETELINK Delete a gPLink from a container\n"\
-" EFFECTIVE Lists all GPOs assigned to a machine\n"\
+/* " APPLY Apply all GPOs\n"\ */
+/* " DELETELINK Delete a gPLink from a container\n"\ */
+" REFRESH Lists all GPOs assigned to an account and downloads them\n"\
" GETGPO Lists specified GPO\n"\
" GETLINK Lists gPLink of a containter\n"\
" HELP Prints this help message\n"\
@@ -41,24 +41,27 @@ static int net_ads_gpo_usage(int argc, const char **argv)
return -1;
}
-static int net_ads_gpo_effective(int argc, const char **argv)
+static int net_ads_gpo_refresh(int argc, const char **argv)
{
TALLOC_CTX *mem_ctx;
ADS_STRUCT *ads;
ADS_STATUS status;
- const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
- void *res = NULL;
+ const char *attrs[] = { "userAccountControl", NULL };
+ LDAPMessage *res = NULL;
const char *filter;
char *dn = NULL;
struct GROUP_POLICY_OBJECT *gpo_list;
uint32 uac = 0;
uint32 flags = 0;
+ struct GROUP_POLICY_OBJECT *gpo;
+ NTSTATUS result;
if (argc < 1) {
+ printf("usage: net ads gpo refresh <username|machinename>\n");
return -1;
}
- mem_ctx = talloc_init("net_ads_gpo_effective");
+ mem_ctx = talloc_init("net_ads_gpo_refresh");
if (mem_ctx == NULL) {
return -1;
}
@@ -68,7 +71,8 @@ static int net_ads_gpo_effective(int argc, const char **argv)
goto out;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -98,7 +102,7 @@ static int net_ads_gpo_effective(int argc, const char **argv)
flags |= GPO_LIST_FLAG_MACHINE;
}
- printf("%s: '%s' has dn: '%s'\n",
+ printf("\n%s: '%s' has dn: '%s'\n\n",
(uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
argv[0], dn);
@@ -107,19 +111,34 @@ static int net_ads_gpo_effective(int argc, const char **argv)
goto out;
}
- printf("unsorted full dump of all GPOs for this machine:\n");
+ if (!NT_STATUS_IS_OK(result = check_refresh_gpo_list(ads, mem_ctx, gpo_list))) {
+ printf("failed to refresh GPOs: %s\n", nt_errstr(result));
+ goto out;
+ }
- {
- struct GROUP_POLICY_OBJECT *gpo = gpo_list;
+ for (gpo = gpo_list; gpo; gpo = gpo->next) {
- for (gpo = gpo_list; gpo; gpo = gpo->next) {
- dump_gpo(mem_ctx, gpo);
+ char *server, *share, *nt_path, *unix_path;
+
+ printf("--------------------------------------\n");
+ printf("Name:\t\t\t%s\n", gpo->display_name);
+ printf("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
+ gpo->version,
+ GPO_VERSION_USER(gpo->version),
+ GPO_VERSION_MACHINE(gpo->version));
+
+ result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
+ &server, &share, &nt_path, &unix_path);
+ if (!NT_STATUS_IS_OK(result)) {
+ printf("got: %s\n", nt_errstr(result));
}
+
+ printf("GPO stored on server: %s, share: %s\n", server, share);
+ printf("\tremote path:\t%s\n", nt_path);
+ printf("\tlocal path:\t%s\n", unix_path);
}
- printf("sorted full dump of all GPOs valid for this machine:\n");
-
-out:
+ out:
ads_memfree(ads, dn);
ads_msgfree(ads, res);
@@ -132,24 +151,36 @@ static int net_ads_gpo_list(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
- void *res = NULL;
+ LDAPMessage *res = NULL;
int num_reply = 0;
- void *msg = NULL;
+ LDAPMessage *msg = NULL;
struct GROUP_POLICY_OBJECT gpo;
TALLOC_CTX *mem_ctx;
+ char *dn;
+ const char *attrs[] = {
+ "versionNumber",
+ "flags",
+ "gPCFileSysPath",
+ "displayName",
+ "name",
+ "gPCMachineExtensionNames",
+ "gPCUserExtensionNames",
+ NULL
+ };
mem_ctx = talloc_init("net_ads_gpo_list");
if (mem_ctx == NULL) {
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
status = ads_do_search_all(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
- "(objectclass=groupPolicyContainer)", NULL, &res);
+ "(objectclass=groupPolicyContainer)", attrs, &res);
if (!ADS_ERR_OK(status)) {
d_printf("search failed: %s\n", ads_errstr(status));
goto out;
@@ -161,16 +192,21 @@ static int net_ads_gpo_list(int argc, const char **argv)
/* dump the results */
for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
-
- status = ads_parse_gpo(ads, mem_ctx, msg, ads_get_dn(ads, msg), &gpo);
+
+ if ((dn = ads_get_dn(ads, msg)) == NULL) {
+ goto out;
+ }
+
+ status = ads_parse_gpo(ads, mem_ctx, msg, dn, &gpo);
if (!ADS_ERR_OK(status)) {
d_printf("parse failed: %s\n", ads_errstr(status));
+ ads_memfree(ads, dn);
goto out;
}
- dump_gpo(mem_ctx, &gpo);
-
+ dump_gpo(mem_ctx, &gpo, 1);
+ ads_memfree(ads, dn);
}
out:
@@ -182,13 +218,15 @@ out:
return 0;
}
+#if 0 /* not yet */
+
static int net_ads_gpo_apply(int argc, const char **argv)
{
TALLOC_CTX *mem_ctx;
ADS_STRUCT *ads;
ADS_STATUS status;
const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
- void *res = NULL;
+ LDAPMessage *res = NULL;
const char *filter;
char *dn = NULL;
struct GROUP_POLICY_OBJECT *gpo_list;
@@ -196,6 +234,7 @@ static int net_ads_gpo_apply(int argc, const char **argv)
uint32 flags = 0;
if (argc < 1) {
+ printf("usage: net ads gpo apply <username|machinename>\n");
return -1;
}
@@ -209,7 +248,8 @@ static int net_ads_gpo_apply(int argc, const char **argv)
goto out;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -263,6 +303,7 @@ out:
return 0;
}
+#endif
static int net_ads_gpo_get_link(int argc, const char **argv)
{
@@ -272,6 +313,7 @@ static int net_ads_gpo_get_link(int argc, const char **argv)
struct GP_LINK gp_link;
if (argc < 1) {
+ printf("usage: net ads gpo getlink <linkname>\n");
return -1;
}
@@ -280,7 +322,8 @@ static int net_ads_gpo_get_link(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -307,6 +350,7 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
TALLOC_CTX *mem_ctx;
if (argc < 2) {
+ printf("usage: net ads gpo addlink <linkdn> <gpodn> [options]\n");
return -1;
}
@@ -319,7 +363,8 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
gpo_opt = atoi(argv[2]);
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -336,6 +381,8 @@ out:
return 0;
}
+#if 0 /* broken */
+
static int net_ads_gpo_delete_link(int argc, const char **argv)
{
ADS_STRUCT *ads;
@@ -351,7 +398,8 @@ static int net_ads_gpo_delete_link(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -368,15 +416,17 @@ out:
return 0;
}
+#endif
+
static int net_ads_gpo_get_gpo(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
TALLOC_CTX *mem_ctx;
struct GROUP_POLICY_OBJECT gpo;
- uint32 sysvol_gpt_version;
if (argc < 1) {
+ printf("usage: net ads gpo getgpo <gpo>\n");
return -1;
}
@@ -385,7 +435,8 @@ static int net_ads_gpo_get_gpo(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_startup())) {
+ status = ads_startup(False, &ads);
+ if (!ADS_ERR_OK(status)) {
goto out;
}
@@ -400,14 +451,7 @@ static int net_ads_gpo_get_gpo(int argc, const char **argv)
goto out;
}
- dump_gpo(mem_ctx, &gpo);
-
- status = ADS_ERROR_NT(ads_gpo_get_sysvol_gpt_version(ads, mem_ctx, gpo.file_sys_path, &sysvol_gpt_version));
- if (!ADS_ERR_OK(status)) {
- goto out;
- }
-
- printf("sysvol GPT version: %d\n", sysvol_gpt_version);
+ dump_gpo(mem_ctx, &gpo, 1);
out:
talloc_destroy(mem_ctx);
@@ -420,17 +464,17 @@ int net_ads_gpo(int argc, const char **argv)
{
struct functable func[] = {
{"LIST", net_ads_gpo_list},
- {"EFFECTIVE", net_ads_gpo_effective},
+ {"REFRESH", net_ads_gpo_refresh},
{"ADDLINK", net_ads_gpo_add_link},
- {"DELETELINK", net_ads_gpo_delete_link},
+ /* {"DELETELINK", net_ads_gpo_delete_link}, */
{"GETLINK", net_ads_gpo_get_link},
{"GETGPO", net_ads_gpo_get_gpo},
{"HELP", net_ads_gpo_usage},
- {"APPLY", net_ads_gpo_apply},
+ /* {"APPLY", net_ads_gpo_apply}, */
{NULL, NULL}
};
return net_run_function(argc, argv, func, net_ads_gpo_usage);
}
-#endif
+#endif /* HAVE_ADS */
diff --git a/source/utils/net_cache.c b/source/utils/net_cache.c
index b90befcca2d..8f394bea85e 100644
--- a/source/utils/net_cache.c
+++ b/source/utils/net_cache.c
@@ -181,47 +181,6 @@ static int net_cache_add(int argc, const char **argv)
return -1;
}
-
-/**
- * Set new value of an existing entry in the cache. Fail If the entry doesn't
- * exist.
- *
- * @param argv key being searched and new value and timeout to set in the entry
- * @return 0 on success, otherwise failure
- **/
-static int net_cache_set(int argc, const char **argv)
-{
- const char *keystr, *datastr, *timeout_str;
- time_t timeout;
-
- if (argc < 3) {
- d_printf("\nUsage: net cache set <key string> <data string> <timeout>\n");
- return -1;
- }
-
- keystr = argv[0];
- datastr = argv[1];
- timeout_str = argv[2];
-
- /* parse timeout given in command line */
- timeout = parse_timeout(timeout_str);
- if (!timeout) {
- d_fprintf(stderr, "Invalid timeout argument.\n");
- return -1;
- }
-
- if (gencache_set_only(keystr, datastr, timeout)) {
- d_printf("Cache entry set successfully.\n");
- gencache_shutdown();
- return 0;
- }
-
- d_fprintf(stderr, "Entry couldn't be set. Perhaps there's no such a key.\n");
- gencache_shutdown();
- return -1;
-}
-
-
/**
* Delete an entry in the cache
*
@@ -334,7 +293,6 @@ static int net_cache_flush(int argc, const char **argv)
static int net_cache_usage(int argc, const char **argv)
{
d_printf(" net cache add \t add add new cache entry\n");
- d_printf(" net cache set \t set new value for existing cache entry\n");
d_printf(" net cache del \t delete existing cache entry by key\n");
d_printf(" net cache flush \t delete all entries existing in the cache\n");
d_printf(" net cache get \t get cache entry by key\n");
@@ -354,7 +312,6 @@ int net_cache(int argc, const char **argv)
{
struct functable func[] = {
{"add", net_cache_add},
- {"set", net_cache_set},
{"del", net_cache_del},
{"get", net_cache_get},
{"search", net_cache_search},
diff --git a/source/utils/net_dns.c b/source/utils/net_dns.c
new file mode 100644
index 00000000000..cd779bf2c33
--- /dev/null
+++ b/source/utils/net_dns.c
@@ -0,0 +1,182 @@
+
+/*
+ Samba Unix/Linux Dynamic DNS Update
+ net ads commands
+
+ Copyright (C) Krishna Ganugapati (krishnag@centeris.com) 2006
+ Copyright (C) Gerald Carter 2006
+
+ 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"
+#include "dns.h"
+
+#if defined(WITH_DNS_UPDATES)
+
+/*********************************************************************
+*********************************************************************/
+
+DNS_ERROR DoDNSUpdate(char *pszServerName,
+ const char *pszDomainName, const char *pszHostName,
+ const struct in_addr *iplist, size_t num_addrs )
+{
+ DNS_ERROR err;
+ struct dns_connection *conn;
+ TALLOC_CTX *mem_ctx;
+ OM_uint32 minor;
+ struct dns_update_request *req, *resp;
+
+ if ( (num_addrs <= 0) || !iplist ) {
+ return ERROR_DNS_INVALID_PARAMETER;
+ }
+
+ if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn );
+ if (!ERR_DNS_IS_OK(err)) {
+ goto error;
+ }
+
+ /*
+ * Probe if everything's fine
+ */
+
+ err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
+ num_addrs, iplist, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * First try without signing
+ */
+
+ err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
+ iplist, num_addrs, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * Okay, we have to try with signing
+ */
+ {
+ gss_ctx_id_t gss_context;
+ char *keyname;
+
+ if (!(keyname = dns_generate_keyname( mem_ctx ))) {
+ err = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+ keyname, &gss_context, DNS_SRV_ANY );
+
+ /* retry using the Windows 2000 DNS hack */
+ if (!ERR_DNS_IS_OK(err)) {
+ err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+ keyname, &gss_context,
+ DNS_SRV_WIN2000 );
+ }
+
+ if (!ERR_DNS_IS_OK(err))
+ goto error;
+
+
+ err = dns_sign_update(req, gss_context, keyname,
+ "gss.microsoft.com", time(NULL), 3600);
+
+ gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
+
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
+ ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
+ }
+
+
+error:
+ TALLOC_FREE(mem_ctx);
+ return err;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+int get_my_ip_address( struct in_addr **ips )
+{
+ struct iface_struct nics[MAX_INTERFACES];
+ int i, n;
+ struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");
+ struct in_addr *list;
+ int count = 0;
+
+ /* find the first non-loopback address from our list of interfaces */
+
+ n = get_interfaces(nics, MAX_INTERFACES);
+
+ if ( (list = SMB_MALLOC_ARRAY( struct in_addr, n )) == NULL ) {
+ return -1;
+ }
+
+ for ( i=0; i<n; i++ ) {
+ if ( nics[i].ip.s_addr != loopback_ip.s_addr ) {
+ memcpy( &list[count++], &nics[i].ip, sizeof( struct in_addr ) );
+ }
+ }
+ *ips = list;
+
+ return count;
+}
+
+DNS_ERROR do_gethostbyname(const char *server, const char *host)
+{
+ struct dns_connection *conn;
+ struct dns_request *req, *resp;
+ DNS_ERROR err;
+
+ err = dns_open_connection(server, DNS_UDP, NULL, &conn);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_create_query(conn, host, QTYPE_A, DNS_CLASS_IN, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_transaction(conn, conn, req, &resp);
+
+ error:
+ TALLOC_FREE(conn);
+ return err;
+}
+
+#endif /* defined(WITH_DNS_UPDATES) */
diff --git a/source/utils/net_domain.c b/source/utils/net_domain.c
index a4a52b23842..5b330d8765c 100644
--- a/source/utils/net_domain.c
+++ b/source/utils/net_domain.c
@@ -157,12 +157,12 @@ int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *
/*******************************************************************
********************************************************************/
-NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, DOM_SID **sid )
+NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ char **domain, DOM_SID **sid )
{
struct rpc_pipe_client *pipe_hnd = NULL;
POLICY_HND lsa_pol;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- char *domain = NULL;
if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
@@ -176,7 +176,7 @@ NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, DOM_
return status;
status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx,
- &lsa_pol, 5, &domain, sid);
+ &lsa_pol, 5, domain, sid);
if ( !NT_STATUS_IS_OK(status) )
return status;
diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c
index 10a672bc1f0..ad1a141cfc5 100644
--- a/source/utils/net_groupmap.c
+++ b/source/utils/net_groupmap.c
@@ -188,11 +188,19 @@ static int net_groupmap_add(int argc, const char **argv)
fstring string_sid = "";
fstring type = "";
fstring ntcomment = "";
- enum SID_NAME_USE sid_type = SID_NAME_DOM_GRP;
+ enum lsa_SidType sid_type = SID_NAME_DOM_GRP;
uint32 rid = 0;
gid_t gid;
int i;
- const char *name_type = "domain group";
+ GROUP_MAP map;
+
+ const char *name_type;
+
+ ZERO_STRUCT(map);
+
+ /* Default is domain group. */
+ map.sid_name_use = SID_NAME_DOM_GRP;
+ name_type = "domain group";
/* get the options */
for ( i=0; i<argc; i++ ) {
@@ -271,7 +279,6 @@ static int net_groupmap_add(int argc, const char **argv)
}
{
- GROUP_MAP map;
if (pdb_getgrgid(&map, gid)) {
d_printf("Unix group %s already mapped to SID %s\n",
unixgrp, sid_string_static(&map.sid));
@@ -325,7 +332,7 @@ static int net_groupmap_add(int argc, const char **argv)
}
d_printf("Successfully added group %s to the mapping db as a %s\n",
- ntgroup, name_type);
+ ntgroup, name_type);
return 0;
}
@@ -338,7 +345,7 @@ static int net_groupmap_modify(int argc, const char **argv)
fstring ntgroup = "";
fstring unixgrp = "";
fstring sid_string = "";
- enum SID_NAME_USE sid_type = SID_NAME_UNKNOWN;
+ enum lsa_SidType sid_type = SID_NAME_UNKNOWN;
int i;
gid_t gid;
@@ -424,13 +431,13 @@ static int net_groupmap_modify(int argc, const char **argv)
if (sid_type == SID_NAME_UNKNOWN) {
d_fprintf(stderr, "Can't map to an unknown group type.\n");
return -1;
- }
+ }
if (map.sid_name_use == SID_NAME_WKN_GRP) {
d_fprintf(stderr, "You can only change between domain and local groups.\n");
return -1;
}
-
+
map.sid_name_use=sid_type;
/* Change comment if new one */
diff --git a/source/utils/net_idmap.c b/source/utils/net_idmap.c
index 47e1f93b69f..dd16c4b02d9 100644
--- a/source/utils/net_idmap.c
+++ b/source/utils/net_idmap.c
@@ -20,186 +20,92 @@
#include "includes.h"
#include "utils/net.h"
-
-/***********************************************************
- Helper function for net_idmap_dump. Dump one entry.
- **********************************************************/
-static int net_idmap_dump_one_entry(TDB_CONTEXT *tdb,
- TDB_DATA key,
- TDB_DATA data,
- void *unused)
-{
- if (strcmp(key.dptr, "USER HWM") == 0) {
- printf("USER HWM %d\n", IVAL(data.dptr,0));
- return 0;
- }
-
- if (strcmp(key.dptr, "GROUP HWM") == 0) {
- printf("GROUP HWM %d\n", IVAL(data.dptr,0));
- return 0;
- }
-
- if (strncmp(key.dptr, "S-", 2) != 0)
- return 0;
-
- printf("%s %s\n", data.dptr, key.dptr);
- return 0;
-}
+#define ALLOC_CHECK(mem) do { \
+ if (!mem) { \
+ d_fprintf(stderr, "Out of memory!\n"); \
+ talloc_free(ctx); \
+ return -1; \
+ } } while(0)
/***********************************************************
Dump the current idmap
**********************************************************/
static int net_idmap_dump(int argc, const char **argv)
{
- TDB_CONTEXT *idmap_tdb;
-
- if ( argc != 1 )
- return net_help_idmap( argc, argv );
-
- idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0);
+ TALLOC_CTX *ctx;
+ char *filename;
- if (idmap_tdb == NULL) {
- d_fprintf(stderr, "Could not open idmap: %s\n", argv[0]);
- return -1;
- }
-
- tdb_traverse(idmap_tdb, net_idmap_dump_one_entry, NULL);
-
- tdb_close(idmap_tdb);
-
- return 0;
-}
-
-/***********************************************************
- Fix up the HWMs after a idmap restore.
- **********************************************************/
-
-struct hwms {
- BOOL ok;
- uid_t user_hwm;
- gid_t group_hwm;
-};
-
-static int net_idmap_find_max_id(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data,
- void *handle)
-{
- struct hwms *hwms = (struct hwms *)handle;
- void *idptr = NULL;
- BOOL isgid = False;
- int id;
-
- if (strncmp(key.dptr, "S-", 2) != 0)
- return 0;
-
- if (sscanf(data.dptr, "GID %d", &id) == 1) {
- idptr = (void *)&hwms->group_hwm;
- isgid = True;
- }
-
- if (sscanf(data.dptr, "UID %d", &id) == 1) {
- idptr = (void *)&hwms->user_hwm;
- isgid = False;
+ if (argc != 1) {
+ return net_help_idmap(argc, argv);
}
- if (idptr == NULL) {
- d_fprintf(stderr, "Illegal idmap entry: [%s]->[%s]\n",
- key.dptr, data.dptr);
- hwms->ok = False;
+ if (! winbind_ping()) {
+ d_fprintf(stderr, "To use net idmap Winbindd must be running.\n");
return -1;
}
- if (isgid) {
- if (hwms->group_hwm <= (gid_t)id) {
- hwms->group_hwm = (gid_t)(id+1);
- }
- } else {
- if (hwms->user_hwm <= (uid_t)id) {
- hwms->user_hwm = (uid_t)(id+1);
+ ctx = talloc_new(NULL);
+ ALLOC_CHECK(ctx);
+
+ filename = talloc_strdup(ctx, argv[0]);
+ ALLOC_CHECK(filename);
+
+ /* filename must be absolute */
+ if (*filename != '/') {
+ char path[4096];
+
+ filename = getcwd(path, 4095);
+ if ( ! filename) {
+ d_fprintf(stderr, "Failed to obtain full output file path");
+ talloc_free(ctx);
+ return -1;
}
- }
-
- return 0;
-}
-
-static NTSTATUS net_idmap_fixup_hwm(void)
-{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- TDB_CONTEXT *idmap_tdb;
- char *tdbfile = NULL;
-
- struct hwms hwms;
- struct hwms highest;
-
- if (!lp_idmap_uid(&hwms.user_hwm, &highest.user_hwm) ||
- !lp_idmap_gid(&hwms.group_hwm, &highest.group_hwm)) {
- d_fprintf(stderr, "idmap range missing\n");
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- tdbfile = SMB_STRDUP(lock_path("winbindd_idmap.tdb"));
- if (!tdbfile) {
- DEBUG(0, ("idmap_init: out of memory!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- idmap_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0);
-
- if (idmap_tdb == NULL) {
- d_fprintf(stderr, "Could not open idmap: %s\n", tdbfile);
- return NT_STATUS_NO_SUCH_FILE;
- }
-
- hwms.ok = True;
-
- tdb_traverse(idmap_tdb, net_idmap_find_max_id, &hwms);
-
- if (!hwms.ok) {
- goto done;
- }
- d_printf("USER HWM: %d GROUP HWM: %d\n",
- hwms.user_hwm, hwms.group_hwm);
-
- if (hwms.user_hwm >= highest.user_hwm) {
- d_fprintf(stderr, "Highest UID out of uid range\n");
- goto done;
- }
-
- if (hwms.group_hwm >= highest.group_hwm) {
- d_fprintf(stderr, "Highest GID out of gid range\n");
- goto done;
+ filename = talloc_asprintf(ctx, "%s/%s", path, argv[0]);
+ ALLOC_CHECK(filename);
}
- if ((tdb_store_int32(idmap_tdb, "USER HWM", (int32)hwms.user_hwm) != 0) ||
- (tdb_store_int32(idmap_tdb, "GROUP HWM", (int32)hwms.group_hwm) != 0)) {
- d_fprintf(stderr, "Could not store HWMs\n");
- goto done;
+ if ( ! winbind_idmap_dump_maps(ctx, filename)) {
+ d_fprintf(stderr, "Failed to obtain idmap data from winbindd\n");
+ talloc_free(ctx);
+ return -1;
}
- result = NT_STATUS_OK;
- done:
- tdb_close(idmap_tdb);
- return result;
+ talloc_free(ctx);
+ return 0;
}
/***********************************************************
Write entries from stdin to current local idmap
**********************************************************/
+
static int net_idmap_restore(int argc, const char **argv)
{
- if (!idmap_init(lp_idmap_backend())) {
- d_fprintf(stderr, "Could not init idmap\n");
+ TALLOC_CTX *ctx;
+ FILE *input;
+
+ if (! winbind_ping()) {
+ d_fprintf(stderr, "To use net idmap Winbindd must be running.\n");
return -1;
}
- while (!feof(stdin)) {
- fstring line, sid_string, fmt_string;
+ ctx = talloc_new(NULL);
+ ALLOC_CHECK(ctx);
+
+ if (argc == 1) {
+ input = fopen(argv[0], "r");
+ } else {
+ input = stdin;
+ }
+
+ while (!feof(input)) {
+ char line[128], sid_string[128];
int len;
- unid_t id;
- int type = ID_EMPTY;
DOM_SID sid;
+ struct id_map map;
+ unsigned long idval;
- if (fgets(line, sizeof(line)-1, stdin) == NULL)
+ if (fgets(line, 127, input) == NULL)
break;
len = strlen(line);
@@ -207,43 +113,50 @@ static int net_idmap_restore(int argc, const char **argv)
if ( (len > 0) && (line[len-1] == '\n') )
line[len-1] = '\0';
- /* Yuck - this is broken for sizeof(gid_t) != sizeof(int) */
- snprintf(fmt_string, sizeof(fmt_string), "GID %%d %%%us", FSTRING_LEN);
- if (sscanf(line, fmt_string, &id.gid, sid_string) == 2) {
- type = ID_GROUPID;
- }
-
- /* Yuck - this is broken for sizeof(uid_t) != sizeof(int) */
-
- snprintf(fmt_string, sizeof(fmt_string), "UID %%d %%%us", FSTRING_LEN);
- if (sscanf(line, fmt_string, &id.uid, sid_string) == 2) {
- type = ID_USERID;
- }
-
- if (type == ID_EMPTY) {
- d_printf("ignoring invalid line [%s]\n", line);
+ if (sscanf(line, "GID %lu %128s", &idval, sid_string) == 2) {
+ map.xid.type = ID_TYPE_GID;
+ map.xid.id = idval;
+ } else if (sscanf(line, "UID %lu %128s", &idval, sid_string) == 2) {
+ map.xid.type = ID_TYPE_UID;
+ map.xid.id = idval;
+ } else if (sscanf(line, "USER HWM %lu", &idval) == 1) {
+ /* set uid hwm */
+ if (! winbind_set_uid_hwm(idval)) {
+ d_fprintf(stderr, "Could not set USER HWM\n");
+ }
+ continue;
+ } else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) {
+ /* set gid hwm */
+ if (! winbind_set_gid_hwm(idval)) {
+ d_fprintf(stderr, "Could not set GROUP HWM\n");
+ }
+ continue;
+ } else {
+ d_fprintf(stderr, "ignoring invalid line [%s]\n", line);
continue;
}
if (!string_to_sid(&sid, sid_string)) {
- d_printf("ignoring invalid sid [%s]\n", sid_string);
+ d_fprintf(stderr, "ignoring invalid sid [%s]\n", sid_string);
continue;
}
+ map.sid = &sid;
- if (!NT_STATUS_IS_OK(idmap_set_mapping(&sid, id, type))) {
+ if (!winbind_set_mapping(&map)) {
d_fprintf(stderr, "Could not set mapping of %s %lu to sid %s\n",
- (type == ID_GROUPID) ? "GID" : "UID",
- (type == ID_GROUPID) ? (unsigned long)id.gid:
- (unsigned long)id.uid,
- sid_string_static(&sid));
+ (map.xid.type == ID_TYPE_GID) ? "GID" : "UID",
+ (unsigned long)map.xid.id, sid_string_static(map.sid));
continue;
}
-
+
}
- idmap_close();
+ if (input != stdin) {
+ fclose(input);
+ }
- return NT_STATUS_IS_OK(net_idmap_fixup_hwm()) ? 0 : -1;
+ talloc_free(ctx);
+ return 0;
}
/***********************************************************
@@ -251,62 +164,122 @@ static int net_idmap_restore(int argc, const char **argv)
**********************************************************/
static int net_idmap_delete(int argc, const char **argv)
{
- TDB_CONTEXT *idmap_tdb;
- TDB_DATA key, data;
- fstring sid;
-
- if (argc != 2)
- return net_help_idmap(argc, argv);
+ d_printf("Not Implemented yet\n");
+ return -1;
+}
- idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDWR, 0);
+static int net_idmap_set(int argc, const char **argv)
+{
+ d_printf("Not Implemented yet\n");
+ return -1;
+}
+BOOL idmap_store_secret(const char *backend, bool alloc,
+ const char *domain, const char *identity,
+ const char *secret)
+{
+ char *tmp;
+ int r;
+ BOOL ret;
- if (idmap_tdb == NULL) {
- d_fprintf(stderr, "Could not open idmap: %s\n", argv[0]);
- return -1;
+ if (alloc) {
+ r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
+ } else {
+ r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
}
- fstrcpy(sid, argv[1]);
+ if (r < 0) return false;
- if (strncmp(sid, "S-1-5-", strlen("S-1-5-")) != 0) {
- d_fprintf(stderr, "Can only delete SIDs, %s is does not start with "
- "S-1-5-\n", sid);
- return -1;
+ strupper_m(tmp); /* make sure the key is case insensitive */
+ ret = secrets_store_generic(tmp, identity, secret);
+
+ free(tmp);
+ return ret;
+}
+
+
+static int net_idmap_secret(int argc, const char **argv)
+{
+ TALLOC_CTX *ctx;
+ const char *secret;
+ const char *dn;
+ char *domain;
+ char *backend;
+ char *opt = NULL;
+ BOOL ret;
+
+ if (argc != 2) {
+ return net_help_idmap(argc, argv);
}
- key.dptr = sid;
- key.dsize = strlen(key.dptr)+1;
+ secret = argv[1];
- data = tdb_fetch(idmap_tdb, key);
+ ctx = talloc_new(NULL);
+ ALLOC_CHECK(ctx);
- if (data.dptr == NULL) {
- d_fprintf(stderr, "Could not find sid %s\n", argv[1]);
- return -1;
+ if (strcmp(argv[0], "alloc") == 0) {
+ domain = NULL;
+ backend = lp_idmap_alloc_backend();
+ } else {
+ domain = talloc_strdup(ctx, argv[0]);
+ ALLOC_CHECK(domain);
+
+ opt = talloc_asprintf(ctx, "idmap config %s", domain);
+ ALLOC_CHECK(opt);
+
+ backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb"));
+ ALLOC_CHECK(backend);
}
- if (tdb_delete(idmap_tdb, key) != 0) {
- d_fprintf(stderr, "Could not delete key %s\n", argv[1]);
+ if ( ( ! backend) || ( ! strequal(backend, "ldap"))) {
+ d_fprintf(stderr, "The only currently supported backend is LDAP\n");
+ talloc_free(ctx);
return -1;
}
- if (tdb_delete(idmap_tdb, data) != 0) {
- d_fprintf(stderr, "Could not delete key %s\n", data.dptr);
+ if (domain) {
+
+ dn = lp_parm_const_string(-1, opt, "ldap_user_dn", NULL);
+ if ( ! dn) {
+ d_fprintf(stderr, "Missing ldap_user_dn option for domain %s\n", domain);
+ talloc_free(ctx);
+ return -1;
+ }
+
+ ret = idmap_store_secret("ldap", false, domain, dn, secret);
+ } else {
+ dn = lp_parm_const_string(-1, "idmap alloc config", "ldap_user_dn", NULL);
+ if ( ! dn) {
+ d_fprintf(stderr, "Missing ldap_user_dn option for alloc backend\n");
+ talloc_free(ctx);
+ return -1;
+ }
+
+ ret = idmap_store_secret("ldap", true, NULL, dn, secret);
+ }
+
+ if ( ! ret) {
+ d_fprintf(stderr, "Failed to store secret\n");
+ talloc_free(ctx);
return -1;
}
+ d_printf("Secret stored\n");
return 0;
}
-
int net_help_idmap(int argc, const char **argv)
{
- d_printf("net idmap dump <tdbfile>"\
- "\n Dump current id mapping\n");
+ d_printf("net idmap dump <outputfile>\n"\
+ " Dump current id mapping\n");
- d_printf("net idmap restore"\
- "\n Restore entries from stdin to current local idmap\n");
+ d_printf("net idmap restore\n"\
+ " Restore entries from stdin\n");
/* Deliberately *not* document net idmap delete */
+ d_printf("net idmap secret <DOMAIN>|alloc <secret>\n"\
+ " Set the secret for the specified DOMAIN (or the alloc module)\n");
+
return -1;
}
@@ -318,7 +291,9 @@ int net_idmap(int argc, const char **argv)
struct functable func[] = {
{"dump", net_idmap_dump},
{"restore", net_idmap_restore},
+ {"setmap", net_idmap_set },
{"delete", net_idmap_delete},
+ {"secret", net_idmap_secret},
{"help", net_help_idmap},
{NULL, NULL}
};
diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c
index 68097aa9f7f..19ba5ae7f46 100644
--- a/source/utils/net_lookup.c
+++ b/source/utils/net_lookup.c
@@ -84,6 +84,7 @@ static int net_lookup_ldap(int argc, const char **argv)
struct hostent *hostent;
struct dns_rr_srv *dcs = NULL;
int numdcs = 0;
+ char *sitename;
TALLOC_CTX *ctx;
NTSTATUS status;
@@ -92,24 +93,28 @@ static int net_lookup_ldap(int argc, const char **argv)
else
domain = opt_target_workgroup;
+ sitename = sitename_fetch(domain);
+
if ( (ctx = talloc_init("net_lookup_ldap")) == NULL ) {
d_fprintf(stderr, "net_lookup_ldap: talloc_inti() failed!\n");
+ SAFE_FREE(sitename);
return -1;
}
DEBUG(9, ("Lookup up ldap for domain %s\n", domain));
- status = ads_dns_query_dcs( ctx, domain, &dcs, &numdcs );
+ status = ads_dns_query_dcs( ctx, domain, sitename, &dcs, &numdcs );
if ( NT_STATUS_IS_OK(status) && numdcs ) {
print_ldap_srvlist(dcs, numdcs);
TALLOC_FREE( ctx );
-
+ SAFE_FREE(sitename);
return 0;
}
DEBUG(9, ("Looking up DC for domain %s\n", domain));
if (!get_pdc_ip(domain, &addr)) {
TALLOC_FREE( ctx );
+ SAFE_FREE(sitename);
return -1;
}
@@ -117,6 +122,7 @@ static int net_lookup_ldap(int argc, const char **argv)
AF_INET);
if (!hostent) {
TALLOC_FREE( ctx );
+ SAFE_FREE(sitename);
return -1;
}
@@ -124,22 +130,23 @@ static int net_lookup_ldap(int argc, const char **argv)
domain = strchr(hostent->h_name, '.');
if (!domain) {
TALLOC_FREE( ctx );
+ SAFE_FREE(sitename);
return -1;
}
domain++;
DEBUG(9, ("Looking up ldap for domain %s\n", domain));
- status = ads_dns_query_dcs( ctx, domain, &dcs, &numdcs );
+ status = ads_dns_query_dcs( ctx, domain, sitename, &dcs, &numdcs );
if ( NT_STATUS_IS_OK(status) && numdcs ) {
print_ldap_srvlist(dcs, numdcs);
TALLOC_FREE( ctx );
-
+ SAFE_FREE(sitename);
return 0;
}
TALLOC_FREE( ctx );
-
+ SAFE_FREE(sitename);
return -1;
#endif
@@ -153,6 +160,7 @@ static int net_lookup_dc(int argc, const char **argv)
struct in_addr addr;
char *pdc_str = NULL;
const char *domain=opt_target_workgroup;
+ char *sitename = NULL;
int count, i;
if (argc > 0)
@@ -165,10 +173,13 @@ static int net_lookup_dc(int argc, const char **argv)
asprintf(&pdc_str, "%s", inet_ntoa(addr));
d_printf("%s\n", pdc_str);
- if (!get_sorted_dc_list(domain, &ip_list, &count, False)) {
+ sitename = sitename_fetch(domain);
+ if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, sitename, &ip_list, &count, False))) {
SAFE_FREE(pdc_str);
+ SAFE_FREE(sitename);
return 0;
}
+ SAFE_FREE(sitename);
for (i=0;i<count;i++) {
char *dc_str = inet_ntoa(ip_list[i].ip);
if (!strequal(pdc_str, dc_str))
@@ -211,11 +222,11 @@ static int net_lookup_kdc(int argc, const char **argv)
}
if (argc>0) {
- realm.data = CONST_DISCARD(krb5_pointer, argv[0]);
+ realm.data = CONST_DISCARD(char *, argv[0]);
realm.length = strlen(argv[0]);
} else if (lp_realm() && *lp_realm()) {
- realm.data = (krb5_pointer) lp_realm();
- realm.length = strlen(realm.data);
+ realm.data = lp_realm();
+ realm.length = strlen((const char *)realm.data);
} else {
rc = krb5_get_host_realm(ctx, NULL, &realms);
if (rc) {
@@ -223,8 +234,8 @@ static int net_lookup_kdc(int argc, const char **argv)
error_message(rc)));
return -1;
}
- realm.data = (krb5_pointer) *realms;
- realm.length = strlen(realm.data);
+ realm.data = (char *) *realms;
+ realm.length = strlen((const char *)realm.data);
}
rc = krb5_locate_kdc(ctx, &realm, (struct sockaddr **)(void *)&addrs, &num_kdcs, 0);
@@ -247,7 +258,7 @@ static int net_lookup_name(int argc, const char **argv)
{
const char *dom, *name;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (argc != 1) {
d_printf("usage: net lookup name <name>\n");
@@ -269,7 +280,7 @@ static int net_lookup_sid(int argc, const char **argv)
{
const char *dom, *name;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (argc != 1) {
d_printf("usage: net lookup sid <sid>\n");
diff --git a/source/utils/net_rap.c b/source/utils/net_rap.c
index ef5df435357..9084122d680 100644
--- a/source/utils/net_rap.c
+++ b/source/utils/net_rap.c
@@ -407,12 +407,40 @@ int net_rap_server_usage(int argc, const char **argv)
net_common_flags_usage(argc, argv);
return -1;
}
+
+static int net_rap_server_name(int argc, const char *argv[])
+{
+ struct cli_state *cli;
+ char *name;
+
+ if (!(cli = net_make_ipc_connection(0)))
+ return -1;
+
+ if (!cli_get_server_name(NULL, cli, &name)) {
+ d_fprintf(stderr, "cli_get_server_name failed\n");
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ d_printf("Server name = %s\n", name);
+
+ TALLOC_FREE(name);
+ cli_shutdown(cli);
+ return 0;
+}
int net_rap_server(int argc, const char **argv)
{
struct cli_state *cli;
int ret;
-
+
+ if (argc > 0) {
+ if (!strequal(argv[0], "name")) {
+ return net_rap_server_usage(argc-1, argv+1);
+ }
+ return net_rap_server_name(argc, argv);
+ }
+
if (!(cli = net_make_ipc_connection(0)))
return -1;
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 190992e3741..9678036d523 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -462,7 +462,7 @@ NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
d_printf("Domain SID: %s\n", sid_str);
- d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num.low);
+ d_printf("Sequence number: %llu\n", (unsigned long long)ctr.info.inf2.seq_num);
d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
@@ -1330,7 +1330,7 @@ static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
DOM_SID sid;
uint32 rid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
if (argc == 0) {
d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
@@ -2008,10 +2008,10 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli,
TALLOC_CTX *mem_ctx,
const char *name,
DOM_SID *sid,
- enum SID_NAME_USE *type)
+ enum lsa_SidType *type)
{
DOM_SID *sids = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
struct rpc_pipe_client *pipe_hnd;
POLICY_HND lsa_pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -2131,7 +2131,7 @@ static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
POLICY_HND alias_pol;
DOM_SID member_sid;
- enum SID_NAME_USE member_type;
+ enum lsa_SidType member_type;
DOM_SID sid;
@@ -2192,7 +2192,7 @@ static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
const char **argv)
{
DOM_SID group_sid;
- enum SID_NAME_USE group_type;
+ enum lsa_SidType group_type;
if (argc != 2) {
d_printf("Usage: 'net rpc group addmem <group> <member>\n");
@@ -2308,7 +2308,7 @@ static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
POLICY_HND alias_pol;
DOM_SID member_sid;
- enum SID_NAME_USE member_type;
+ enum lsa_SidType member_type;
DOM_SID sid;
@@ -2366,7 +2366,7 @@ static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
const char **argv)
{
DOM_SID group_sid;
- enum SID_NAME_USE group_type;
+ enum lsa_SidType group_type;
if (argc != 2) {
d_printf("Usage: 'net rpc group delmem <group> <member>\n");
@@ -2717,7 +2717,7 @@ static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
DOM_SID *alias_sids;
char **domains;
char **names;
- uint32 *types;
+ enum lsa_SidType *types;
int i;
result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
@@ -5654,6 +5654,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
domain_name, nt_errstr(nt_status)));
+ return -1;
}
/*
@@ -5663,6 +5664,8 @@ static int rpc_trustdom_establish(int argc, const char **argv)
if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
for domain %s\n", domain_name));
+ cli_shutdown(cli);
+ return -1;
}
if (!(mem_ctx = talloc_init("establishing trust relationship to "
@@ -6269,7 +6272,7 @@ static int rpc_trustdom(int argc, const char **argv)
*/
BOOL net_rpc_check(unsigned flags)
{
- struct cli_state cli;
+ struct cli_state *cli;
BOOL ret = False;
struct in_addr server_ip;
char *server_name = NULL;
@@ -6278,23 +6281,23 @@ BOOL net_rpc_check(unsigned flags)
if (!net_find_server(NULL, flags, &server_ip, &server_name))
return False;
- ZERO_STRUCT(cli);
- if (cli_initialise(&cli) == False)
+ if ((cli = cli_initialise()) == NULL) {
return False;
+ }
- if (!cli_connect(&cli, server_name, &server_ip))
+ if (!cli_connect(cli, server_name, &server_ip))
goto done;
if (!attempt_netbios_session_request(&cli, global_myname(),
server_name, &server_ip))
goto done;
- if (!cli_negprot(&cli))
+ if (!cli_negprot(cli))
goto done;
- if (cli.protocol < PROTOCOL_NT1)
+ if (cli->protocol < PROTOCOL_NT1)
goto done;
ret = True;
done:
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return ret;
}
diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c
index 0dd28c3ac67..11c4991e7d7 100644
--- a/source/utils/net_rpc_rights.c
+++ b/source/utils/net_rpc_rights.c
@@ -29,7 +29,7 @@ static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
fstring name)
{
POLICY_HND pol;
- uint32 *sid_types;
+ enum lsa_SidType *sid_types;
NTSTATUS result;
char **domains, **names;
@@ -60,7 +60,7 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
DOM_SID *sid, const char *name)
{
POLICY_HND pol;
- uint32 *sid_types;
+ enum lsa_SidType *sid_types;
NTSTATUS result;
DOM_SID *sids;
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index b29acc8a106..3e19a12ac52 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -42,44 +42,6 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g)
d_printf("\n");
}
-static const char *display_time(NTTIME *nttime)
-{
- static fstring string;
-
- float high;
- float low;
- int sec;
- int days, hours, mins, secs;
- int offset = 1;
-
- if (nttime->high==0 && nttime->low==0)
- return "Now";
-
- if (nttime->high==0x80000000 && nttime->low==0)
- return "Never";
-
- high = 65536;
- high = high/10000;
- high = high*65536;
- high = high/1000;
- high = high * (~nttime->high);
-
- low = ~nttime->low;
- low = low/(1000*1000*10);
-
- sec=high+low;
- sec+=offset;
-
- days=sec/(60*60*24);
- hours=(sec - (days*60*60*24)) / (60*60);
- mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
- secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
-
- fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
- return (string);
-}
-
-
static void display_alias_info(uint32 rid, SAM_ALIAS_INFO *a)
{
d_printf("Alias '%s' ", unistr2_static(&a->uni_als_name));
@@ -123,11 +85,18 @@ static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a)
pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN));
}
+static time_t uint64s_nt_time_to_unix_abs(const uint64 *src)
+{
+ NTTIME nttime;
+ nttime = *src;
+ return nt_time_to_unix_abs(&nttime);
+}
+
static void display_domain_info(SAM_DOMAIN_INFO *a)
{
time_t u_logout;
- u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff);
+ u_logout = uint64s_nt_time_to_unix_abs(&a->force_logoff);
d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name));
@@ -136,11 +105,11 @@ static void display_domain_info(SAM_DOMAIN_INFO *a)
d_printf("Force Logoff: %d\n", (int)u_logout);
- d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age));
- d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age));
+ d_printf("Max Password Age: %s\n", display_time(a->max_pwd_age));
+ d_printf("Min Password Age: %s\n", display_time(a->min_pwd_age));
- d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration));
- d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count));
+ d_printf("Lockout Time: %s\n", display_time(a->account_lockout.lockout_duration));
+ d_printf("Lockout Reset Time: %s\n", display_time(a->account_lockout.reset_count));
d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout);
d_printf("User must logon to change password: %d\n", a->logon_chgpass);
@@ -243,7 +212,7 @@ static void dump_database(struct rpc_pipe_client *pipe_hnd, uint32 db_type)
result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx, db_type,
sync_context,
&num_deltas, &hdr_deltas, &deltas);
- if (NT_STATUS_IS_ERR(result))
+ if (!NT_STATUS_IS_OK(result))
break;
for (i = 0; i < num_deltas; i++) {
@@ -412,14 +381,14 @@ static NTSTATUS sam_account_from_delta(struct samu *account, SAM_ACCOUNT_INFO *d
/* Logon and password information */
if (!nt_time_is_zero(&delta->logon_time)) {
- unix_time = nt_time_to_unix(&delta->logon_time);
+ unix_time = nt_time_to_unix(delta->logon_time);
stored_time = pdb_get_logon_time(account);
if (stored_time != unix_time)
pdb_set_logon_time(account, unix_time, PDB_CHANGED);
}
if (!nt_time_is_zero(&delta->logoff_time)) {
- unix_time = nt_time_to_unix(&delta->logoff_time);
+ unix_time = nt_time_to_unix(delta->logoff_time);
stored_time = pdb_get_logoff_time(account);
if (stored_time != unix_time)
pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
@@ -455,7 +424,7 @@ static NTSTATUS sam_account_from_delta(struct samu *account, SAM_ACCOUNT_INFO *d
pdb_set_logon_count(account, delta->logon_count, PDB_CHANGED);
if (!nt_time_is_zero(&delta->pwd_last_set_time)) {
- unix_time = nt_time_to_unix(&delta->pwd_last_set_time);
+ unix_time = nt_time_to_unix(delta->pwd_last_set_time);
stored_time = pdb_get_pass_last_set_time(account);
if (stored_time != unix_time)
pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
@@ -861,11 +830,11 @@ static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
pstring domname;
- u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age);
- u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age);
- u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff);
- u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count);
- u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration);
+ u_max_age = uint64s_nt_time_to_unix_abs(&delta->max_pwd_age);
+ u_min_age = uint64s_nt_time_to_unix_abs(&delta->min_pwd_age);
+ u_logout = uint64s_nt_time_to_unix_abs(&delta->force_logoff);
+ u_lockoutreset = uint64s_nt_time_to_unix_abs(&delta->account_lockout.reset_count);
+ u_lockouttime = uint64s_nt_time_to_unix_abs(&delta->account_lockout.lockout_duration);
unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1);
@@ -1355,6 +1324,68 @@ static NTSTATUS map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap,
return NT_STATUS_OK;
}
+/*
+ * This is a crap routine, but I think it's the quickest way to solve the
+ * UTF8->base64 problem.
+ */
+
+static int fprintf_attr(FILE *add_fd, const char *attr_name,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *value, *p, *base64;
+ DATA_BLOB base64_blob;
+ BOOL do_base64 = False;
+ int res;
+
+ va_start(ap, fmt);
+ value = talloc_vasprintf(NULL, fmt, ap);
+ va_end(ap);
+
+ SMB_ASSERT(value != NULL);
+
+ for (p=value; *p; p++) {
+ if (*p & 0x80) {
+ do_base64 = True;
+ break;
+ }
+ }
+
+ if (!do_base64) {
+ BOOL only_whitespace = True;
+ for (p=value; *p; p++) {
+ /*
+ * I know that this not multibyte safe, but we break
+ * on the first non-whitespace character anyway.
+ */
+ if (!isspace(*p)) {
+ only_whitespace = False;
+ break;
+ }
+ }
+ if (only_whitespace) {
+ do_base64 = True;
+ }
+ }
+
+ if (!do_base64) {
+ res = fprintf(add_fd, "%s: %s\n", attr_name, value);
+ TALLOC_FREE(value);
+ return res;
+ }
+
+ base64_blob.data = (unsigned char *)value;
+ base64_blob.length = strlen(value);
+
+ base64 = base64_encode_data_blob(base64_blob);
+ SMB_ASSERT(base64 != NULL);
+
+ res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
+ TALLOC_FREE(value);
+ SAFE_FREE(base64);
+ return res;
+}
+
static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
FILE *add_fd, fstring sid, char *suffix)
{
@@ -1397,15 +1428,15 @@ static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
/* Write the data to the temporary add ldif file */
fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
suffix);
- fprintf(add_fd, "dn: cn=%s,ou=%s,%s\n", groupname, group_attr,
- suffix);
+ fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
+ suffix);
fprintf(add_fd, "objectClass: posixGroup\n");
fprintf(add_fd, "objectClass: sambaGroupMapping\n");
- fprintf(add_fd, "cn: %s\n", groupname);
+ fprintf_attr(add_fd, "cn", "%s", groupname);
fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
- fprintf(add_fd, "displayName: %s\n", groupname);
+ fprintf_attr(add_fd, "displayName", "%s", groupname);
fprintf(add_fd, "\n");
fflush(add_fd);
@@ -1414,15 +1445,19 @@ static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
return NT_STATUS_OK;
}
-static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
- ACCOUNTMAP *accountmap, FILE *add_fd,
- fstring sid, char *suffix, int alloced)
+static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta,
+ GROUPMAP *groupmap,
+ ACCOUNTMAP *accountmap,
+ FILE *add_fd,
+ fstring sid, char *suffix,
+ int alloced)
{
fstring username, logonscript, homedrive, homepath = "", homedir = "";
fstring hex_nt_passwd, hex_lm_passwd;
- fstring description, fullname, sambaSID;
+ fstring description, profilepath, fullname, sambaSID;
uchar lm_passwd[16], nt_passwd[16];
char *flags, *user_rdn;
+ const char *ou;
const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
static uchar zero_buf[16];
uint32 rid = 0, group_rid = 0, gidNumber = 0;
@@ -1450,27 +1485,36 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
} else {
pstr_sprintf(homedir, "/nobodyshomedir");
}
- }
+ ou = lp_ldap_user_suffix();
+ } else {
+ ou = lp_ldap_machine_suffix();
+ pstr_sprintf(homedir, "/machinehomedir");
+ }
/* Get the logon script */
unistr2_to_ascii(logonscript, &(delta->account_info.uni_logon_script),
- sizeof(logonscript)-1);
+ sizeof(logonscript)-1);
/* Get the home drive */
unistr2_to_ascii(homedrive, &(delta->account_info.uni_dir_drive),
- sizeof(homedrive)-1);
+ sizeof(homedrive)-1);
+
+ /* Get the home path */
+ unistr2_to_ascii(homepath, &(delta->account_info.uni_home_dir),
+ sizeof(homepath)-1);
/* Get the description */
unistr2_to_ascii(description, &(delta->account_info.uni_acct_desc),
sizeof(description)-1);
- if (!*description) {
- pstr_sprintf(description, "System User");
- }
/* Get the display name */
unistr2_to_ascii(fullname, &(delta->account_info.uni_full_name),
sizeof(fullname)-1);
+ /* Get the profile path */
+ unistr2_to_ascii(profilepath, &(delta->account_info.uni_profile),
+ sizeof(profilepath)-1);
+
/* Get lm and nt password data */
if (memcmp(delta->account_info.pass.buf_lm_pwd, zero_buf, 16) != 0) {
sam_pwd_hash(delta->account_info.user_rid,
@@ -1484,21 +1528,16 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
if (memcmp(delta->account_info.pass.buf_nt_pwd, zero_buf, 16) != 0) {
sam_pwd_hash(delta->account_info.user_rid,
delta->account_info.pass.buf_nt_pwd,
- nt_passwd, 0);
+ nt_passwd, 0);
pdb_sethexpwd(hex_nt_passwd, nt_passwd,
delta->account_info.acb_info);
} else {
pdb_sethexpwd(hex_nt_passwd, NULL, 0);
}
- unix_time = nt_time_to_unix(&(delta->account_info.pwd_last_set_time));
+ unix_time = nt_time_to_unix(delta->account_info.pwd_last_set_time);
- /* The nobody user is entered by populate_ldap_for_ldif */
- if (strcmp(username, "nobody") == 0) {
- return NT_STATUS_OK;
- } else {
- /* Increment the uid for the new user */
- ldif_uid++;
- }
+ /* Increment the uid for the new user */
+ ldif_uid++;
/* Set up group id and sambaSID for the user */
group_rid = delta->account_info.group_rid;
@@ -1519,36 +1558,40 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
/* Add the user to the temporary add ldif file */
/* this isn't quite right...we can't assume there's just OU=. jmcd */
- user_rdn = sstring_sub(lp_ldap_user_suffix(), '=', ',');
+ user_rdn = sstring_sub(ou, '=', ',');
fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
- fprintf(add_fd, "dn: uid=%s,ou=%s,%s\n", username, user_rdn, suffix);
+ fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
+ suffix);
SAFE_FREE(user_rdn);
fprintf(add_fd, "ObjectClass: top\n");
fprintf(add_fd, "objectClass: inetOrgPerson\n");
fprintf(add_fd, "objectClass: posixAccount\n");
fprintf(add_fd, "objectClass: shadowAccount\n");
fprintf(add_fd, "objectClass: sambaSamAccount\n");
- fprintf(add_fd, "cn: %s\n", username);
- fprintf(add_fd, "sn: %s\n", username);
- fprintf(add_fd, "uid: %s\n", username);
+ fprintf_attr(add_fd, "cn", "%s", username);
+ fprintf_attr(add_fd, "sn", "%s", username);
+ fprintf_attr(add_fd, "uid", "%s", username);
fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
fprintf(add_fd, "gidNumber: %d\n", gidNumber);
- fprintf(add_fd, "homeDirectory: %s\n", homedir);
+ fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
if (*homepath)
- fprintf(add_fd, "SambaHomePath: %s\n", homepath);
+ fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
if (*homedrive)
- fprintf(add_fd, "SambaHomeDrive: %s\n", homedrive);
+ fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
if (*logonscript)
- fprintf(add_fd, "SambaLogonScript: %s\n", logonscript);
+ fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
fprintf(add_fd, "loginShell: %s\n",
((delta->account_info.acb_info & ACB_NORMAL) ?
"/bin/bash" : "/bin/false"));
fprintf(add_fd, "gecos: System User\n");
- fprintf(add_fd, "description: %s\n", description);
+ if (*description)
+ fprintf_attr(add_fd, "description", "%s", description);
fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
if(*fullname)
- fprintf(add_fd, "displayName: %s\n", fullname);
+ fprintf_attr(add_fd, "displayName", "%s", fullname);
+ if(*profilepath)
+ fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
if (strcmp(nopasswd, hex_lm_passwd) != 0)
fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
if (strcmp(nopasswd, hex_nt_passwd) != 0)
@@ -1562,9 +1605,11 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
return NT_STATUS_OK;
}
-static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
- FILE *add_fd, fstring sid, char *suffix,
- unsigned db_type)
+static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta,
+ GROUPMAP *groupmap,
+ FILE *add_fd, fstring sid,
+ char *suffix,
+ unsigned db_type)
{
fstring aliasname, description;
uint32 grouptype = 0, g_rid = 0;
@@ -1580,21 +1625,21 @@ static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
/* Set up the group type */
switch (db_type) {
- case SAM_DATABASE_DOMAIN:
- grouptype = 4;
- break;
- case SAM_DATABASE_BUILTIN:
- grouptype = 5;
- break;
- default:
- grouptype = 4;
- break;
+ case SAM_DATABASE_DOMAIN:
+ grouptype = 4;
+ break;
+ case SAM_DATABASE_BUILTIN:
+ grouptype = 5;
+ break;
+ default:
+ grouptype = 4;
+ break;
}
/*
- These groups are entered by populate_ldap_for_ldif
- Note that populate creates a group called Relicators,
- but NT returns a group called Replicator
+ These groups are entered by populate_ldap_for_ldif
+ Note that populate creates a group called Relicators,
+ but NT returns a group called Replicator
*/
if (strcmp(aliasname, "Domain Admins") == 0 ||
strcmp(aliasname, "Domain Users") == 0 ||
@@ -1619,16 +1664,17 @@ static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
/* Write the data to the temporary add ldif file */
fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
suffix);
- fprintf(add_fd, "dn: cn=%s,ou=%s,%s\n", aliasname, group_attr,
- suffix);
+ fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
+ suffix);
fprintf(add_fd, "objectClass: posixGroup\n");
fprintf(add_fd, "objectClass: sambaGroupMapping\n");
fprintf(add_fd, "cn: %s\n", aliasname);
fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
- fprintf(add_fd, "displayName: %s\n", aliasname);
- fprintf(add_fd, "description: %s\n", description);
+ fprintf_attr(add_fd, "displayName", "%s", aliasname);
+ if (description[0])
+ fprintf_attr(add_fd, "description", "%s", description);
fprintf(add_fd, "\n");
fflush(add_fd);
@@ -1637,9 +1683,11 @@ static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
return NT_STATUS_OK;
}
-static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta,
- GROUPMAP *groupmap, ACCOUNTMAP *accountmap,
- FILE *mod_fd, int alloced)
+static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta,
+ SAM_DELTA_HDR *hdr_delta,
+ GROUPMAP *groupmap,
+ ACCOUNTMAP *accountmap,
+ FILE *mod_fd, int alloced)
{
fstring group_dn;
uint32 group_rid = 0, rid = 0;
@@ -1666,7 +1714,8 @@ static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR
if (accountmap[k].rid == rid) break;
}
if (k == alloced){
- DEBUG(1, ("Could not find rid %d in accountmap array\n", rid));
+ DEBUG(1, ("Could not find rid %d in "
+ "accountmap array\n", rid));
return NT_STATUS_UNSUCCESSFUL;
}
fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
@@ -1680,9 +1729,9 @@ static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR
}
static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
- uint32 db_type,
- DOM_SID dom_sid,
- const char *user_file)
+ uint32 db_type,
+ DOM_SID dom_sid,
+ const char *user_file)
{
char *suffix;
const char *builtin_sid = "S-1-5-32";
@@ -1780,7 +1829,7 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Initial database population */
populate_ldap_for_ldif(sid, suffix, builtin_sid, add_file);
map_populate_groups(groupmap, accountmap, sid, suffix,
- builtin_sid);
+ builtin_sid);
/* Don't do this again */
init_ldap = 0;
@@ -1788,27 +1837,27 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Announce what we are doing */
switch( db_type ) {
- case SAM_DATABASE_DOMAIN:
- d_fprintf(stderr, "Fetching DOMAIN database\n");
- break;
- case SAM_DATABASE_BUILTIN:
- d_fprintf(stderr, "Fetching BUILTIN database\n");
- break;
- case SAM_DATABASE_PRIVS:
- d_fprintf(stderr, "Fetching PRIVS databases\n");
- break;
- default:
- d_fprintf(stderr,
- "Fetching unknown database type %u\n",
- db_type );
- break;
+ case SAM_DATABASE_DOMAIN:
+ d_fprintf(stderr, "Fetching DOMAIN database\n");
+ break;
+ case SAM_DATABASE_BUILTIN:
+ d_fprintf(stderr, "Fetching BUILTIN database\n");
+ break;
+ case SAM_DATABASE_PRIVS:
+ d_fprintf(stderr, "Fetching PRIVS databases\n");
+ break;
+ default:
+ d_fprintf(stderr,
+ "Fetching unknown database type %u\n",
+ db_type );
+ break;
}
do {
result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx,
- db_type, sync_context,
- &num_deltas, &hdr_deltas,
- &deltas);
+ db_type, sync_context,
+ &num_deltas, &hdr_deltas,
+ &deltas);
if (!NT_STATUS_IS_OK(result) &&
!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
ret = NT_STATUS_OK;
@@ -1817,9 +1866,9 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Re-allocate memory for groupmap and accountmap arrays */
groupmap = SMB_REALLOC_ARRAY(groupmap, GROUPMAP,
- num_deltas+num_alloced);
+ num_deltas+num_alloced);
accountmap = SMB_REALLOC_ARRAY(accountmap, ACCOUNTMAP,
- num_deltas+num_alloced);
+ num_deltas+num_alloced);
if (groupmap == NULL || accountmap == NULL) {
DEBUG(1,("GROUPMAP malloc failed\n"));
ret = NT_STATUS_NO_MEMORY;
@@ -1838,72 +1887,73 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Loop through the deltas */
for (k=0; k<num_deltas; k++) {
switch(hdr_deltas[k].type) {
- case SAM_DELTA_DOMAIN_INFO:
- /* Is this case needed? */
- unistr2_to_ascii(domainname,
- &deltas[k].domain_info.uni_dom_name,
- sizeof(domainname)-1);
- break;
-
- case SAM_DELTA_GROUP_INFO:
- fetch_group_info_to_ldif(
- &deltas[k], &groupmap[g_index],
- add_file, sid, suffix);
- g_index++;
- break;
-
- case SAM_DELTA_ACCOUNT_INFO:
- fetch_account_info_to_ldif(
- &deltas[k], groupmap,
- &accountmap[a_index], add_file,
- sid, suffix, num_alloced);
- a_index++;
- break;
-
- case SAM_DELTA_ALIAS_INFO:
- fetch_alias_info_to_ldif(
- &deltas[k], &groupmap[g_index],
- add_file, sid, suffix, db_type);
- g_index++;
- break;
-
- case SAM_DELTA_GROUP_MEM:
- fetch_groupmem_info_to_ldif(
- &deltas[k], &hdr_deltas[k],
- groupmap, accountmap,
- mod_file, num_alloced);
- break;
-
- case SAM_DELTA_ALIAS_MEM:
- break;
- case SAM_DELTA_POLICY_INFO:
- break;
- case SAM_DELTA_PRIVS_INFO:
- break;
- case SAM_DELTA_TRUST_DOMS:
- /* Implemented but broken */
- break;
- case SAM_DELTA_SECRET_INFO:
- /* Implemented but broken */
- break;
- case SAM_DELTA_RENAME_GROUP:
- /* Not yet implemented */
- break;
- case SAM_DELTA_RENAME_USER:
- /* Not yet implemented */
- break;
- case SAM_DELTA_RENAME_ALIAS:
- /* Not yet implemented */
- break;
- case SAM_DELTA_DELETE_GROUP:
- /* Not yet implemented */
- break;
- case SAM_DELTA_DELETE_USER:
- /* Not yet implemented */
- break;
- case SAM_DELTA_MODIFIED_COUNT:
- break;
- default:
+ case SAM_DELTA_DOMAIN_INFO:
+ /* Is this case needed? */
+ unistr2_to_ascii(
+ domainname,
+ &deltas[k].domain_info.uni_dom_name,
+ sizeof(domainname)-1);
+ break;
+
+ case SAM_DELTA_GROUP_INFO:
+ fetch_group_info_to_ldif(
+ &deltas[k], &groupmap[g_index],
+ add_file, sid, suffix);
+ g_index++;
+ break;
+
+ case SAM_DELTA_ACCOUNT_INFO:
+ fetch_account_info_to_ldif(
+ &deltas[k], groupmap,
+ &accountmap[a_index], add_file,
+ sid, suffix, num_alloced);
+ a_index++;
+ break;
+
+ case SAM_DELTA_ALIAS_INFO:
+ fetch_alias_info_to_ldif(
+ &deltas[k], &groupmap[g_index],
+ add_file, sid, suffix, db_type);
+ g_index++;
+ break;
+
+ case SAM_DELTA_GROUP_MEM:
+ fetch_groupmem_info_to_ldif(
+ &deltas[k], &hdr_deltas[k],
+ groupmap, accountmap,
+ mod_file, num_alloced);
+ break;
+
+ case SAM_DELTA_ALIAS_MEM:
+ break;
+ case SAM_DELTA_POLICY_INFO:
+ break;
+ case SAM_DELTA_PRIVS_INFO:
+ break;
+ case SAM_DELTA_TRUST_DOMS:
+ /* Implemented but broken */
+ break;
+ case SAM_DELTA_SECRET_INFO:
+ /* Implemented but broken */
+ break;
+ case SAM_DELTA_RENAME_GROUP:
+ /* Not yet implemented */
+ break;
+ case SAM_DELTA_RENAME_USER:
+ /* Not yet implemented */
+ break;
+ case SAM_DELTA_RENAME_ALIAS:
+ /* Not yet implemented */
+ break;
+ case SAM_DELTA_DELETE_GROUP:
+ /* Not yet implemented */
+ break;
+ case SAM_DELTA_DELETE_USER:
+ /* Not yet implemented */
+ break;
+ case SAM_DELTA_MODIFIED_COUNT:
+ break;
+ default:
break;
} /* end of switch */
} /* end of for loop */
@@ -1947,13 +1997,14 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
transfer_file(fileno(mod_file), fileno(ldif_file), (size_t) -1);
- done:
+ done:
/* Close and delete the ldif files */
if (add_file) {
fclose(add_file);
}
- if ((add_name != NULL) && strcmp(add_name, add_template) && (unlink(add_name))) {
+ if ((add_name != NULL) &&
+ strcmp(add_name, add_template) && (unlink(add_name))) {
DEBUG(1,("unlink(%s) failed, error was (%s)\n",
add_name, strerror(errno)));
}
@@ -1962,7 +2013,8 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
fclose(mod_file);
}
- if ((mod_name != NULL) && strcmp(mod_name, mod_template) && (unlink(mod_name))) {
+ if ((mod_name != NULL) &&
+ strcmp(mod_name, mod_template) && (unlink(mod_name))) {
DEBUG(1,("unlink(%s) failed, error was (%s)\n",
mod_name, strerror(errno)));
}
@@ -1989,10 +2041,11 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
int rpc_vampire_usage(int argc, const char **argv)
{
- d_printf("net rpc vampire [ldif [<ldif-filename>] [options]\n"\
- "\t to pull accounts from a remote PDC where we are a BDC\n"\
- "\t\t no args puts accounts in local passdb from smb.conf\n"\
- "\t\t ldif - put accounts in ldif format (file defaults to /tmp/tmp.ldif\n");
+ d_printf("net rpc vampire [ldif [<ldif-filename>] [options]\n"
+ "\t to pull accounts from a remote PDC where we are a BDC\n"
+ "\t\t no args puts accounts in local passdb from smb.conf\n"
+ "\t\t ldif - put accounts in ldif format (file defaults to "
+ "/tmp/tmp.ldif\n");
net_common_flags_usage(argc, argv);
return -1;
@@ -2016,47 +2069,52 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid,
d_printf("Cannot import users from %s at this time, "
"as the current domain:\n\t%s: %s\nconflicts "
"with the remote domain\n\t%s: %s\n"
- "Perhaps you need to set: \n\n\tsecurity=user\n\tworkgroup=%s\n\n in your smb.conf?\n",
+ "Perhaps you need to set: \n\n\tsecurity=user\n\t"
+ "workgroup=%s\n\n in your smb.conf?\n",
domain_name,
- get_global_sam_name(), sid_to_string(my_dom_sid_str,
- get_global_sam_sid()),
- domain_name, sid_to_string(rem_dom_sid_str, domain_sid),
+ get_global_sam_name(),
+ sid_to_string(my_dom_sid_str,
+ get_global_sam_sid()),
+ domain_name, sid_to_string(rem_dom_sid_str,
+ domain_sid),
domain_name);
return NT_STATUS_UNSUCCESSFUL;
}
if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) {
result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_DOMAIN,
- *domain_sid, argv[1]);
+ *domain_sid, argv[1]);
} else {
- result = fetch_database(pipe_hnd, SAM_DATABASE_DOMAIN, *domain_sid);
+ result = fetch_database(pipe_hnd, SAM_DATABASE_DOMAIN,
+ *domain_sid);
}
if (!NT_STATUS_IS_OK(result)) {
d_fprintf(stderr, "Failed to fetch domain database: %s\n",
- nt_errstr(result));
+ nt_errstr(result));
if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED))
- d_fprintf(stderr, "Perhaps %s is a Windows 2000 native "
- "mode domain?\n", domain_name);
+ d_fprintf(stderr, "Perhaps %s is a Windows 2000 "
+ "native mode domain?\n", domain_name);
goto fail;
}
if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) {
- result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_BUILTIN,
- global_sid_Builtin, argv[1]);
+ result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_BUILTIN,
+ global_sid_Builtin, argv[1]);
} else {
- result = fetch_database(pipe_hnd, SAM_DATABASE_BUILTIN, global_sid_Builtin);
+ result = fetch_database(pipe_hnd, SAM_DATABASE_BUILTIN,
+ global_sid_Builtin);
}
if (!NT_STATUS_IS_OK(result)) {
d_fprintf(stderr, "Failed to fetch builtin database: %s\n",
- nt_errstr(result));
+ nt_errstr(result));
goto fail;
}
/* Currently we crash on PRIVS somewhere in unmarshalling */
/* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
-fail:
+ fail:
return result;
}
diff --git a/source/utils/net_rpc_service.c b/source/utils/net_rpc_service.c
index 27127a1c3f9..58a5b27f400 100644
--- a/source/utils/net_rpc_service.c
+++ b/source/utils/net_rpc_service.c
@@ -80,7 +80,7 @@ static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd,
d_printf(".");
i++;
- usleep( 100 );
+ sys_usleep( 100 );
}
d_printf("\n");
diff --git a/source/utils/net_sam.c b/source/utils/net_sam.c
index 654c9ec5b2a..8800cb36060 100644
--- a/source/utils/net_sam.c
+++ b/source/utils/net_sam.c
@@ -32,7 +32,7 @@ static int net_sam_userset(int argc, const char **argv, const char *field,
{
struct samu *sam_acct = NULL;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dom, *name;
NTSTATUS status;
@@ -127,7 +127,7 @@ static int net_sam_set_userflag(int argc, const char **argv, const char *field,
{
struct samu *sam_acct = NULL;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dom, *name;
NTSTATUS status;
uint16 acct_flags;
@@ -206,23 +206,20 @@ static int net_sam_set_pwnoexp(int argc, const char **argv)
}
/*
- * Set a user's time field
+ * Set pass last change time, based on force pass change now
*/
-static int net_sam_set_time(int argc, const char **argv, const char *field,
- BOOL (*fn)(struct samu *, time_t,
- enum pdb_value_state))
+static int net_sam_set_pwdmustchangenow(int argc, const char **argv)
{
struct samu *sam_acct = NULL;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dom, *name;
NTSTATUS status;
- time_t new_time;
- if (argc != 2) {
- d_fprintf(stderr, "usage: net sam set %s <user> "
- "[now|YYYY-MM-DD HH:MM]\n", field);
+ if ((argc != 2) || (!strequal(argv[1], "yes") &&
+ !strequal(argv[1], "no"))) {
+ d_fprintf(stderr, "usage: net sam set pwdmustchangenow <user> [yes|no]\n");
return -1;
}
@@ -238,22 +235,6 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
return -1;
}
- if (strequal(argv[1], "now")) {
- new_time = time(NULL);
- } else {
- struct tm tm;
- char *end;
- ZERO_STRUCT(tm);
- end = strptime(argv[1], "%Y-%m-%d %H:%M", &tm);
- new_time = mktime(&tm);
- if ((end == NULL) || (*end != '\0') || (new_time == -1)) {
- d_fprintf(stderr, "Could not parse time string %s\n",
- argv[1]);
- return -1;
- }
- }
-
-
if ( !(sam_acct = samu_new( NULL )) ) {
d_fprintf(stderr, "Internal error\n");
return -1;
@@ -264,9 +245,10 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
return -1;
}
- if (!fn(sam_acct, new_time, PDB_CHANGED)) {
- d_fprintf(stderr, "Internal error\n");
- return -1;
+ if (strequal(argv[1], "yes")) {
+ pdb_set_pass_last_set_time(sam_acct, 0, PDB_CHANGED);
+ } else {
+ pdb_set_pass_last_set_time(sam_acct, time(NULL), PDB_CHANGED);
}
status = pdb_update_sam_account(sam_acct);
@@ -278,21 +260,11 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
TALLOC_FREE(sam_acct);
- d_printf("Updated %s for %s\\%s to %s\n", field, dom, name, argv[1]);
+ d_fprintf(stderr, "Updated 'user must change password at next logon' for %s\\%s to %s\n", dom,
+ name, argv[1]);
return 0;
}
-static int net_sam_set_pwdmustchange(int argc, const char **argv)
-{
- return net_sam_set_time(argc, argv, "pwdmustchange",
- pdb_set_pass_must_change_time);
-}
-
-static int net_sam_set_pwdcanchange(int argc, const char **argv)
-{
- return net_sam_set_time(argc, argv, "pwdcanchange",
- pdb_set_pass_can_change_time);
-}
/*
* Set a user's or a group's comment
@@ -302,7 +274,7 @@ static int net_sam_set_comment(int argc, const char **argv)
{
GROUP_MAP map;
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dom, *name;
NTSTATUS status;
@@ -376,10 +348,8 @@ static int net_sam_set(int argc, const char **argv)
"Disable/Enable a user's lockout flag" },
{ "pwnoexp", net_sam_set_pwnoexp,
"Disable/Enable whether a user's pw does not expire" },
- { "pwdmustchange", net_sam_set_pwdmustchange,
- "Set a users password must change time" },
- { "pwdcanchange", net_sam_set_pwdcanchange,
- "Set a users password can change time" },
+ { "pwdmustchangenow", net_sam_set_pwdmustchangenow,
+ "Force users password must change at next logon" },
{NULL, NULL}
};
@@ -387,6 +357,153 @@ static int net_sam_set(int argc, const char **argv)
}
/*
+ * Manage account policies
+ */
+
+static int net_sam_policy_set(int argc, const char **argv)
+{
+ const char *account_policy = NULL;
+ uint32 value, old_value;
+ int field;
+ char *endptr;
+
+ if (argc != 2) {
+ d_fprintf(stderr, "usage: net sam policy set "
+ "\"<account policy>\" <value> \n");
+ return -1;
+ }
+
+ account_policy = argv[0];
+ field = account_policy_name_to_fieldnum(account_policy);
+
+ if (strequal(argv[1], "forever") || strequal(argv[1], "never")
+ || strequal(argv[1], "off")) {
+ value = -1;
+ }
+ else {
+ value = strtoul(argv[1], &endptr, 10);
+
+ if ((endptr == argv[1]) || (endptr[0] != '\0')) {
+ d_printf("Unable to set policy \"%s\"! Invalid value "
+ "\"%s\".\n",
+ account_policy, argv[1]);
+ return -1;
+ }
+ }
+
+ if (field == 0) {
+ const char **names;
+ int i, count;
+
+ account_policy_names_list(&names, &count);
+ d_fprintf(stderr, "No account policy \"%s\"!\n\n", argv[0]);
+ d_fprintf(stderr, "Valid account policies are:\n");
+
+ for (i=0; i<count; i++) {
+ d_fprintf(stderr, "%s\n", names[i]);
+ }
+
+ SAFE_FREE(names);
+ return -1;
+ }
+
+ if (!pdb_get_account_policy(field, &old_value)) {
+ d_fprintf(stderr, "Valid account policy, but unable to fetch "
+ "value!\n");
+ }
+
+ if (!pdb_set_account_policy(field, value)) {
+ d_fprintf(stderr, "Valid account policy, but unable to "
+ "set value!\n");
+ return -1;
+ }
+
+ d_printf("Account policy \"%s\" value was: %d\n", account_policy,
+ old_value);
+
+ d_printf("Account policy \"%s\" value is now: %d\n", account_policy,
+ value);
+ return 0;
+}
+
+static int net_sam_policy_show(int argc, const char **argv)
+{
+ const char *account_policy = NULL;
+ uint32 old_value;
+ int field;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam policy show"
+ " \"<account policy>\" \n");
+ return -1;
+ }
+
+ account_policy = argv[0];
+ field = account_policy_name_to_fieldnum(account_policy);
+
+ if (field == 0) {
+ const char **names;
+ int count;
+ int i;
+ account_policy_names_list(&names, &count);
+ d_fprintf(stderr, "No account policy by that name!\n");
+ if (count != 0) {
+ d_fprintf(stderr, "Valid account policies "
+ "are:\n");
+ for (i=0; i<count; i++) {
+ d_fprintf(stderr, "%s\n", names[i]);
+ }
+ }
+ SAFE_FREE(names);
+ return -1;
+ }
+
+ if (!pdb_get_account_policy(field, &old_value)) {
+ fprintf(stderr, "Valid account policy, but unable to "
+ "fetch value!\n");
+ return -1;
+ }
+
+ printf("Account policy \"%s\" description: %s\n",
+ account_policy, account_policy_get_desc(field));
+ printf("Account policy \"%s\" value is: %d\n", account_policy,
+ old_value);
+ return 0;
+}
+
+static int net_sam_policy_list(int argc, const char **argv)
+{
+ const char **names;
+ int count;
+ int i;
+ account_policy_names_list(&names, &count);
+ if (count != 0) {
+ d_fprintf(stderr, "Valid account policies "
+ "are:\n");
+ for (i = 0; i < count ; i++) {
+ d_fprintf(stderr, "%s\n", names[i]);
+ }
+ }
+ SAFE_FREE(names);
+ return -1;
+}
+
+static int net_sam_policy(int argc, const char **argv)
+{
+ struct functable2 func[] = {
+ { "list", net_sam_policy_list,
+ "List account policies" },
+ { "show", net_sam_policy_show,
+ "Show account policies" },
+ { "set", net_sam_policy_set,
+ "Change account policies" },
+ {NULL, NULL}
+ };
+
+ return net_run_function2(argc, argv, "net sam policy", func);
+}
+
+/*
* Map a unix group to a domain group
*/
@@ -462,7 +579,7 @@ static int net_sam_createbuiltingroup(int argc, const char **argv)
{
NTSTATUS status;
uint32 rid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
fstring groupname;
DOM_SID sid;
@@ -514,7 +631,7 @@ static int net_sam_addmem(int argc, const char **argv)
{
const char *groupdomain, *groupname, *memberdomain, *membername;
DOM_SID group, member;
- enum SID_NAME_USE grouptype, membertype;
+ enum lsa_SidType grouptype, membertype;
NTSTATUS status;
if (argc != 2) {
@@ -587,7 +704,7 @@ static int net_sam_delmem(int argc, const char **argv)
const char *memberdomain = NULL;
const char *membername = NULL;
DOM_SID group, member;
- enum SID_NAME_USE grouptype;
+ enum lsa_SidType grouptype;
NTSTATUS status;
if (argc != 2) {
@@ -645,7 +762,7 @@ static int net_sam_listmem(int argc, const char **argv)
{
const char *groupdomain, *groupname;
DOM_SID group;
- enum SID_NAME_USE grouptype;
+ enum lsa_SidType grouptype;
NTSTATUS status;
if (argc != 1) {
@@ -793,7 +910,7 @@ static int net_sam_list(int argc, const char **argv)
static int net_sam_show(int argc, const char **argv)
{
DOM_SID sid;
- enum SID_NAME_USE type;
+ enum lsa_SidType type;
const char *dom, *name;
if (argc != 1) {
@@ -1232,6 +1349,8 @@ int net_sam(int argc, const char **argv)
"Show details of a SAM entry" },
{ "set", net_sam_set,
"Set details of a SAM account" },
+ { "policy", net_sam_policy,
+ "Set account policies" },
#ifdef HAVE_LDAP
{ "provision", net_sam_provision,
"Provision a clean User Database" },
diff --git a/source/utils/net_time.c b/source/utils/net_time.c
index f6486286a65..f6269627dab 100644
--- a/source/utils/net_time.c
+++ b/source/utils/net_time.c
@@ -30,8 +30,10 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
time_t ret = 0;
struct cli_state *cli = NULL;
- cli = cli_initialise(NULL);
- if (!cli) goto done;
+ cli = cli_initialise();
+ if (!cli) {
+ goto done;
+ }
if (!cli_connect(cli, host, ip)) {
fprintf(stderr,"Can't contact server\n");
@@ -58,7 +60,9 @@ static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
if (zone) *zone = cli->serverzone;
done:
- if (cli) cli_shutdown(cli);
+ if (cli) {
+ cli_shutdown(cli);
+ }
return ret;
}
diff --git a/source/utils/net_usershare.c b/source/utils/net_usershare.c
index 6a306a99830..e867f4c9409 100644
--- a/source/utils/net_usershare.c
+++ b/source/utils/net_usershare.c
@@ -372,7 +372,7 @@ static int info_fn(struct file_list *fl, void *priv)
const char *name;
NTSTATUS ntstatus;
- ntstatus = net_lookup_name_from_sid(ctx, &psd->dacl->ace[num_aces].trustee, &domain, &name);
+ ntstatus = net_lookup_name_from_sid(ctx, &psd->dacl->aces[num_aces].trustee, &domain, &name);
if (NT_STATUS_IS_OK(ntstatus)) {
if (domain && *domain) {
@@ -382,15 +382,15 @@ static int info_fn(struct file_list *fl, void *priv)
pstrcat(acl_str,name);
} else {
fstring sidstr;
- sid_to_string(sidstr, &psd->dacl->ace[num_aces].trustee);
+ sid_to_string(sidstr, &psd->dacl->aces[num_aces].trustee);
pstrcat(acl_str,sidstr);
}
pstrcat(acl_str, ":");
- if (psd->dacl->ace[num_aces].type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ if (psd->dacl->aces[num_aces].type == SEC_ACE_TYPE_ACCESS_DENIED) {
pstrcat(acl_str, "D,");
} else {
- if (psd->dacl->ace[num_aces].info.mask & GENERIC_ALL_ACCESS) {
+ if (psd->dacl->aces[num_aces].access_mask & GENERIC_ALL_ACCESS) {
pstrcat(acl_str, "F,");
} else {
pstrcat(acl_str, "R,");
@@ -568,6 +568,9 @@ static int net_usershare_add(int argc, const char **argv)
us_path = argv[1];
us_comment = argv[2];
arg_acl = argv[3];
+ if (strlen(arg_acl) == 0) {
+ arg_acl = "S-1-1-0:R";
+ }
if (!strnequal(argv[4], "guest_ok=", 9)) {
return net_usershare_add_usage(argc, argv);
}
@@ -588,10 +591,9 @@ static int net_usershare_add(int argc, const char **argv)
/* Ensure we're under the "usershare max shares" number. Advisory only. */
num_usershares = count_num_usershares();
- if (num_usershares > lp_usershare_max_shares()) {
- d_fprintf(stderr, "net usershare add: too many usershares already defined (%d), "
- "maximum number allowed is %d.\n",
- num_usershares, lp_usershare_max_shares() );
+ if (num_usershares >= lp_usershare_max_shares()) {
+ d_fprintf(stderr, "net usershare add: maximum number of allowed usershares (%d) reached\n",
+ lp_usershare_max_shares() );
SAFE_FREE(sharename);
return -1;
}
diff --git a/source/utils/net_util.c b/source/utils/net_util.c
index 805104cefa1..be39a754656 100644
--- a/source/utils/net_util.c
+++ b/source/utils/net_util.c
@@ -32,14 +32,14 @@ BOOL is_valid_policy_hnd(const POLICY_HND *hnd)
NTSTATUS net_rpc_lookup_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
const char *name, const char **ret_domain,
const char **ret_name, DOM_SID *ret_sid,
- enum SID_NAME_USE *ret_type)
+ enum lsa_SidType *ret_type)
{
struct rpc_pipe_client *lsa_pipe;
POLICY_HND pol;
NTSTATUS result = NT_STATUS_OK;
const char **dom_names;
DOM_SID *sids;
- uint32_t *types;
+ enum lsa_SidType *types;
ZERO_STRUCT(pol);
diff --git a/source/utils/netlookup.c b/source/utils/netlookup.c
index 3c33e65391a..33b6c4bb257 100644
--- a/source/utils/netlookup.c
+++ b/source/utils/netlookup.c
@@ -41,7 +41,7 @@ static struct con_struct *cs;
Close connection on context destruction.
********************************************************/
-static int cs_destructor(void *p)
+static int cs_destructor(struct con_struct *p)
{
if (cs->cli) {
cli_shutdown(cs->cli);
@@ -157,7 +157,7 @@ NTSTATUS net_lookup_name_from_sid(TALLOC_CTX *ctx,
struct con_struct *csp = NULL;
char **domains;
char **names;
- uint32 *types;
+ enum lsa_SidType *types;
*ppdomain = NULL;
*ppname = NULL;
@@ -195,7 +195,7 @@ NTSTATUS net_lookup_sid_from_name(TALLOC_CTX *ctx, const char *full_name, DOM_SI
NTSTATUS nt_status;
struct con_struct *csp = NULL;
DOM_SID *sids = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
csp = create_cs(ctx, &nt_status);
if (csp == NULL) {
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index 17f60345171..1e7b361e860 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -6,6 +6,7 @@
Copyright (C) Tim Potter 2000-2003
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000
+ Copyright (C) Robert O'Callahan 2006 (added cached credential code).
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,6 +39,7 @@ enum stdio_helper_mode {
GSS_SPNEGO,
GSS_SPNEGO_CLIENT,
NTLM_SERVER_1,
+ NTLM_CHANGE_PASSWORD_1,
NUM_HELPER_MODES
};
@@ -62,6 +64,8 @@ static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helpe
static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode,
char *buf, int length);
+static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length);
+
static const struct {
enum stdio_helper_mode mode;
const char *name;
@@ -74,6 +78,7 @@ static const struct {
{ GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
{ GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
{ NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
+ { NTLM_CHANGE_PASSWORD_1, "ntlm-change-password-1", manage_ntlm_change_password_1_request},
{ NUM_HELPER_MODES, NULL, NULL}
};
@@ -88,6 +93,7 @@ static DATA_BLOB opt_lm_response;
static DATA_BLOB opt_nt_response;
static int request_lm_key;
static int request_user_session_key;
+static int use_cached_creds;
static const char *require_membership_of;
static const char *require_membership_of_sid;
@@ -266,7 +272,7 @@ static BOOL check_plaintext_auth(const char *user, const char *pass,
fstrcpy(request.data.auth.user, user);
fstrcpy(request.data.auth.pass, pass);
if (require_membership_of_sid)
- fstrcpy(request.data.auth.require_membership_of_sid, require_membership_of_sid);
+ pstrcpy(request.data.auth.require_membership_of_sid, require_membership_of_sid);
result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
@@ -390,10 +396,90 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
free_response(&response);
return nt_status;
}
-
+
+/* contact server to change user password using auth crap */
+static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username,
+ const char *domain,
+ const DATA_BLOB new_nt_pswd,
+ const DATA_BLOB old_nt_hash_enc,
+ const DATA_BLOB new_lm_pswd,
+ const DATA_BLOB old_lm_hash_enc,
+ char **error_string)
+{
+ NTSTATUS nt_status;
+ NSS_STATUS result;
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ if (!get_require_membership_sid())
+ {
+ if(error_string)
+ *error_string = smb_xstrdup("Can't get membership sid.");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if(username != NULL)
+ fstrcpy(request.data.chng_pswd_auth_crap.user, username);
+ if(domain != NULL)
+ fstrcpy(request.data.chng_pswd_auth_crap.domain,domain);
+
+ if(new_nt_pswd.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, new_nt_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_nt_pswd));
+ request.data.chng_pswd_auth_crap.new_nt_pswd_len = new_nt_pswd.length;
+ }
+
+ if(old_nt_hash_enc.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc, old_nt_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_nt_hash_enc));
+ request.data.chng_pswd_auth_crap.old_nt_hash_enc_len = old_nt_hash_enc.length;
+ }
+
+ if(new_lm_pswd.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, new_lm_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_lm_pswd));
+ request.data.chng_pswd_auth_crap.new_lm_pswd_len = new_lm_pswd.length;
+ }
+
+ if(old_lm_hash_enc.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, old_lm_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_lm_hash_enc));
+ request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = old_lm_hash_enc.length;
+ }
+
+ result = winbindd_request_response(WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, &request, &response);
+
+ /* Display response */
+
+ if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0))
+ {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ if (error_string)
+ *error_string = smb_xstrdup("Reading winbind reply failed!");
+ free_response(&response);
+ return nt_status;
+ }
+
+ nt_status = (NT_STATUS(response.data.auth.nt_status));
+ if (!NT_STATUS_IS_OK(nt_status))
+ {
+ if (error_string)
+ *error_string = smb_xstrdup(response.data.auth.error_string);
+ free_response(&response);
+ return nt_status;
+ }
+
+ free_response(&response);
+
+ return nt_status;
+}
+
static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
{
- static const char zeros[16];
+ static const char zeros[16] = { 0, };
NTSTATUS nt_status;
char *error_string;
uint8 lm_key[8];
@@ -499,14 +585,17 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st
return status;
}
- status = ntlmssp_set_password(*client_ntlmssp_state, opt_password);
+ if (opt_password) {
+ status = ntlmssp_set_password(*client_ntlmssp_state, opt_password);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not set password: %s\n",
- nt_errstr(status)));
- ntlmssp_end(client_ntlmssp_state);
- return status;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Could not set password: %s\n",
+ nt_errstr(status)));
+ ntlmssp_end(client_ntlmssp_state);
+ return status;
+ }
}
+
return NT_STATUS_OK;
}
@@ -515,7 +604,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state)
NTSTATUS status = ntlmssp_server_start(ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Could not start NTLMSSP client: %s\n",
+ DEBUG(1, ("Could not start NTLMSSP server: %s\n",
nt_errstr(status)));
return status;
}
@@ -533,10 +622,69 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state)
return NT_STATUS_OK;
}
+/*******************************************************************
+ Used by firefox to drive NTLM auth to IIS servers.
+*******************************************************************/
+
+static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_msg,
+ DATA_BLOB *reply)
+{
+ struct winbindd_request wb_request;
+ struct winbindd_response wb_response;
+ NSS_STATUS result;
+
+ /* get winbindd to do the ntlmssp step on our behalf */
+ ZERO_STRUCT(wb_request);
+ ZERO_STRUCT(wb_response);
+
+ fstr_sprintf(wb_request.data.ccache_ntlm_auth.user,
+ "%s%c%s", opt_domain, winbind_separator(), opt_username);
+ wb_request.data.ccache_ntlm_auth.uid = geteuid();
+ wb_request.data.ccache_ntlm_auth.initial_blob_len = initial_msg.length;
+ wb_request.data.ccache_ntlm_auth.challenge_blob_len = challenge_msg.length;
+ wb_request.extra_len = initial_msg.length + challenge_msg.length;
+
+ if (wb_request.extra_len > 0) {
+ wb_request.extra_data.data = SMB_MALLOC_ARRAY(char, wb_request.extra_len);
+ if (wb_request.extra_data.data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ memcpy(wb_request.extra_data.data, initial_msg.data, initial_msg.length);
+ memcpy(wb_request.extra_data.data + initial_msg.length,
+ challenge_msg.data, challenge_msg.length);
+ }
+
+ result = winbindd_request_response(WINBINDD_CCACHE_NTLMAUTH, &wb_request, &wb_response);
+ SAFE_FREE(wb_request.extra_data.data);
+
+ if (result != NSS_STATUS_SUCCESS) {
+ free_response(&wb_response);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (reply) {
+ *reply = data_blob(wb_response.extra_data.data,
+ wb_response.data.ccache_ntlm_auth.auth_blob_len);
+ if (wb_response.data.ccache_ntlm_auth.auth_blob_len > 0 &&
+ reply->data == NULL) {
+ free_response(&wb_response);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ free_response(&wb_response);
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
static NTLMSSP_STATE *ntlmssp_state = NULL;
+ static char* want_feature_list = NULL;
+ static uint32 neg_flags = 0;
+ static BOOL have_session_key = False;
+ static DATA_BLOB session_key;
DATA_BLOB request, reply;
NTSTATUS nt_status;
@@ -547,6 +695,13 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
}
if (strlen(buf) > 3) {
+ if(strncmp(buf, "SF ", 3) == 0){
+ DEBUG(10, ("Setting flags to negotioate\n"));
+ SAFE_FREE(want_feature_list);
+ want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3);
+ x_fprintf(x_stdout, "OK\n");
+ return;
+ }
request = base64_decode_data_blob(buf + 3);
} else {
request = data_blob(NULL, 0);
@@ -574,6 +729,23 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
ntlmssp_end(&ntlmssp_state);
} else if (strncmp(buf, "KK", 2) == 0) {
+ } else if (strncmp(buf, "GF", 2) == 0) {
+ DEBUG(10, ("Requested negotiated NTLMSSP flags\n"));
+ x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l);
+ data_blob_free(&request);
+ return;
+ } else if (strncmp(buf, "GK", 2) == 0) {
+ DEBUG(10, ("Requested NTLMSSP session key\n"));
+ if(have_session_key) {
+ char *key64 = base64_encode_data_blob(session_key);
+ x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>");
+ SAFE_FREE(key64);
+ } else {
+ x_fprintf(x_stdout, "BH\n");
+ }
+
+ data_blob_free(&request);
+ return;
} else {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
x_fprintf(x_stdout, "BH\n");
@@ -585,6 +757,7 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
return;
}
+ ntlmssp_want_feature_list(ntlmssp_state, want_feature_list);
}
DEBUG(10, ("got NTLMSSP packet:\n"));
@@ -609,6 +782,13 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
} else {
x_fprintf(x_stdout, "AF %s\n", (char *)ntlmssp_state->auth_context);
DEBUG(10, ("NTLMSSP OK!\n"));
+
+ if(have_session_key)
+ data_blob_free(&session_key);
+ session_key = data_blob(ntlmssp_state->session_key.data,
+ ntlmssp_state->session_key.length);
+ neg_flags = ntlmssp_state->neg_flags;
+ have_session_key = True;
}
data_blob_free(&request);
@@ -617,11 +797,25 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
char *buf, int length)
{
+ /* The statics here are *HORRIBLE* and this entire concept
+ needs to be rewritten. Essentially it's using these statics
+ as the state in a state machine. BLEEEGH ! JRA. */
+
static NTLMSSP_STATE *ntlmssp_state = NULL;
+ static DATA_BLOB initial_message;
+ static char* want_feature_list = NULL;
+ static uint32 neg_flags = 0;
+ static BOOL have_session_key = False;
+ static DATA_BLOB session_key;
DATA_BLOB request, reply;
NTSTATUS nt_status;
BOOL first = False;
+ if (!opt_username || !*opt_username) {
+ x_fprintf(x_stderr, "username must be specified!\n\n");
+ exit(1);
+ }
+
if (strlen(buf) < 2) {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
x_fprintf(x_stdout, "BH\n");
@@ -629,6 +823,13 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
}
if (strlen(buf) > 3) {
+ if(strncmp(buf, "SF ", 3) == 0) {
+ DEBUG(10, ("Looking for flags to negotiate\n"));
+ SAFE_FREE(want_feature_list);
+ want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3);
+ x_fprintf(x_stdout, "OK\n");
+ return;
+ }
request = base64_decode_data_blob(buf + 3);
} else {
request = data_blob(NULL, 0);
@@ -651,7 +852,18 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
return;
}
- if (opt_password == NULL) {
+ if (!ntlmssp_state && use_cached_creds) {
+ /* check whether credentials are usable. */
+ DATA_BLOB empty_blob = data_blob(NULL, 0);
+
+ nt_status = do_ccache_ntlm_auth(empty_blob, empty_blob, NULL);
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ /* failed to use cached creds */
+ use_cached_creds = False;
+ }
+ }
+
+ if (opt_password == NULL && !use_cached_creds) {
/* Request a password from the calling process. After
sending it, the calling process should retry asking for the negotiate. */
@@ -666,6 +878,25 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
ntlmssp_end(&ntlmssp_state);
} else if (strncmp(buf, "TT", 2) == 0) {
+ } else if (strncmp(buf, "GF", 2) == 0) {
+ DEBUG(10, ("Requested negotiated NTLMSSP flags\n"));
+ x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l);
+ data_blob_free(&request);
+ return;
+ } else if (strncmp(buf, "GK", 2) == 0 ) {
+ DEBUG(10, ("Requested session key\n"));
+
+ if(have_session_key) {
+ char *key64 = base64_encode_data_blob(session_key);
+ x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>");
+ SAFE_FREE(key64);
+ }
+ else {
+ x_fprintf(x_stdout, "BH\n");
+ }
+
+ data_blob_free(&request);
+ return;
} else {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
x_fprintf(x_stdout, "BH\n");
@@ -677,13 +908,19 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
return;
}
+ ntlmssp_want_feature_list(ntlmssp_state, want_feature_list);
first = True;
+ initial_message = data_blob(NULL, 0);
}
DEBUG(10, ("got NTLMSSP packet:\n"));
dump_data(10, (const char *)request.data, request.length);
- nt_status = ntlmssp_update(ntlmssp_state, request, &reply);
+ if (use_cached_creds && !opt_password && !first) {
+ nt_status = do_ccache_ntlm_auth(initial_message, request, &reply);
+ } else {
+ nt_status = ntlmssp_update(ntlmssp_state, request, &reply);
+ }
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
char *reply_base64 = base64_encode_data_blob(reply);
@@ -693,12 +930,25 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
x_fprintf(x_stdout, "KK %s\n", reply_base64);
}
SAFE_FREE(reply_base64);
- data_blob_free(&reply);
+ if (first) {
+ initial_message = reply;
+ } else {
+ data_blob_free(&reply);
+ }
DEBUG(10, ("NTLMSSP challenge\n"));
} else if (NT_STATUS_IS_OK(nt_status)) {
char *reply_base64 = base64_encode_data_blob(reply);
x_fprintf(x_stdout, "AF %s\n", reply_base64);
SAFE_FREE(reply_base64);
+
+ if(have_session_key)
+ data_blob_free(&session_key);
+
+ session_key = data_blob(ntlmssp_state->session_key.data,
+ ntlmssp_state->session_key.length);
+ neg_flags = ntlmssp_state->neg_flags;
+ have_session_key = True;
+
DEBUG(10, ("NTLMSSP OK!\n"));
if (ntlmssp_state)
ntlmssp_end(&ntlmssp_state);
@@ -718,7 +968,7 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
char *user, *pass;
user=buf;
- pass=memchr(buf,' ',length);
+ pass=(char *)memchr(buf,' ',length);
if (!pass) {
DEBUG(2, ("Password not found. Denying access\n"));
x_fprintf(x_stdout, "ERR\n");
@@ -1162,7 +1412,8 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
return False;
}
- principal = SMB_MALLOC(spnego.negTokenInit.mechListMIC.length+1);
+ principal = (char *)SMB_MALLOC(
+ spnego.negTokenInit.mechListMIC.length+1);
if (principal == NULL) {
DEBUG(1, ("Could not malloc principal\n"));
@@ -1173,7 +1424,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
spnego.negTokenInit.mechListMIC.length);
principal[spnego.negTokenInit.mechListMIC.length] = '\0';
- retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL);
if (retval) {
@@ -1195,7 +1446,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
return False;
}
- retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL);
if (retval) {
DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
@@ -1260,6 +1511,11 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper
SPNEGO_DATA spnego;
ssize_t len;
+ if (!opt_username || !*opt_username) {
+ x_fprintf(x_stderr, "username must be specified!\n\n");
+ exit(1);
+ }
+
if (strlen(buf) <= 3) {
DEBUG(1, ("SPNEGO query [%s] too short\n", buf));
x_fprintf(x_stdout, "BH\n");
@@ -1579,6 +1835,216 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
}
}
+static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length)
+{
+ char *request, *parameter;
+ static DATA_BLOB new_nt_pswd;
+ static DATA_BLOB old_nt_hash_enc;
+ static DATA_BLOB new_lm_pswd;
+ static DATA_BLOB old_lm_hash_enc;
+ static char *full_username = NULL;
+ static char *username = NULL;
+ static char *domain = NULL;
+ static char *newpswd = NULL;
+ static char *oldpswd = NULL;
+
+ if (strequal(buf, ".")) {
+ if(newpswd && oldpswd) {
+ uchar old_nt_hash[16];
+ uchar old_lm_hash[16];
+ uchar new_nt_hash[16];
+ uchar new_lm_hash[16];
+
+ new_nt_pswd = data_blob(NULL, 516);
+ old_nt_hash_enc = data_blob(NULL, 16);
+
+ /* Calculate the MD4 hash (NT compatible) of the
+ * password */
+ E_md4hash(oldpswd, old_nt_hash);
+ E_md4hash(newpswd, new_nt_hash);
+
+ /* E_deshash returns false for 'long'
+ passwords (> 14 DOS chars).
+
+ Therefore, don't send a buffer
+ encrypted with the truncated hash
+ (it could allow an even easier
+ attack on the password)
+
+ Likewise, obey the admin's restriction
+ */
+
+ if (lp_client_lanman_auth() &&
+ E_deshash(newpswd, new_lm_hash) &&
+ E_deshash(oldpswd, old_lm_hash)) {
+ new_lm_pswd = data_blob(NULL, 516);
+ old_lm_hash_enc = data_blob(NULL, 16);
+ encode_pw_buffer(new_lm_pswd.data, newpswd,
+ STR_UNICODE);
+
+ SamOEMhash(new_lm_pswd.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_lm_hash,
+ old_lm_hash_enc.data);
+ } else {
+ new_lm_pswd.data = NULL;
+ new_lm_pswd.length = 0;
+ old_lm_hash_enc.data = NULL;
+ old_lm_hash_enc.length = 0;
+ }
+
+ encode_pw_buffer(new_nt_pswd.data, newpswd,
+ STR_UNICODE);
+
+ SamOEMhash(new_nt_pswd.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_nt_hash,
+ old_nt_hash_enc.data);
+ }
+
+ if (!full_username && !username) {
+ x_fprintf(x_stdout, "Error: No username supplied!\n");
+ } else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) &&
+ (!new_lm_pswd.data || old_lm_hash_enc.data) ) {
+ x_fprintf(x_stdout, "Error: No NT or LM password "
+ "blobs supplied!\n");
+ } else {
+ char *error_string = NULL;
+
+ if (full_username && !username) {
+ fstring fstr_user;
+ fstring fstr_domain;
+
+ if (!parse_ntlm_auth_domain_user(full_username,
+ fstr_user,
+ fstr_domain)) {
+ /* username might be 'tainted', don't
+ * print into our new-line
+ * deleimianted stream */
+ x_fprintf(x_stdout, "Error: Could not "
+ "parse into domain and "
+ "username\n");
+ SAFE_FREE(username);
+ username = smb_xstrdup(full_username);
+ } else {
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ username = smb_xstrdup(fstr_user);
+ domain = smb_xstrdup(fstr_domain);
+ }
+
+ }
+
+ if(!NT_STATUS_IS_OK(contact_winbind_change_pswd_auth_crap(
+ username, domain,
+ new_nt_pswd,
+ old_nt_hash_enc,
+ new_lm_pswd,
+ old_lm_hash_enc,
+ &error_string))) {
+ x_fprintf(x_stdout, "Password-Change: No\n");
+ x_fprintf(x_stdout, "Password-Change-Error: "
+ "%s\n.\n", error_string);
+ } else {
+ x_fprintf(x_stdout, "Password-Change: Yes\n");
+ }
+
+ SAFE_FREE(error_string);
+ }
+ /* clear out the state */
+ new_nt_pswd = data_blob(NULL, 0);
+ old_nt_hash_enc = data_blob(NULL, 0);
+ new_lm_pswd = data_blob(NULL, 0);
+ old_nt_hash_enc = data_blob(NULL, 0);
+ SAFE_FREE(full_username);
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(newpswd);
+ SAFE_FREE(oldpswd);
+ x_fprintf(x_stdout, ".\n");
+
+ return;
+ }
+
+ request = buf;
+
+ /* Indicates a base64 encoded structure */
+ parameter = strstr_m(request, ":: ");
+ if (!parameter) {
+ parameter = strstr_m(request, ": ");
+
+ if (!parameter) {
+ DEBUG(0, ("Parameter not found!\n"));
+ x_fprintf(x_stdout, "Error: Parameter not found!\n.\n");
+ return;
+ }
+
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+ } else {
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+ parameter[0] ='\0';
+ parameter++;
+
+ base64_decode_inplace(parameter);
+ }
+
+ if (strequal(request, "new-nt-password-blob")) {
+ new_nt_pswd = strhex_to_data_blob(NULL, parameter);
+ if (new_nt_pswd.length != 516) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! "
+ "(got %d bytes, expected 516)\n.\n",
+ parameter,
+ (int)new_nt_pswd.length);
+ new_nt_pswd = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "old-nt-hash-blob")) {
+ old_nt_hash_enc = strhex_to_data_blob(NULL, parameter);
+ if (old_nt_hash_enc.length != 16) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! "
+ "(got %d bytes, expected 16)\n.\n",
+ parameter,
+ (int)old_nt_hash_enc.length);
+ old_nt_hash_enc = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "new-lm-password-blob")) {
+ new_lm_pswd = strhex_to_data_blob(NULL, parameter);
+ if (new_lm_pswd.length != 516) {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! "
+ "(got %d bytes, expected 516)\n.\n",
+ parameter,
+ (int)new_lm_pswd.length);
+ new_lm_pswd = data_blob(NULL, 0);
+ }
+ }
+ else if (strequal(request, "old-lm-hash-blob")) {
+ old_lm_hash_enc = strhex_to_data_blob(NULL, parameter);
+ if (old_lm_hash_enc.length != 16)
+ {
+ x_fprintf(x_stdout, "Error: hex decode of %s failed! "
+ "(got %d bytes, expected 16)\n.\n",
+ parameter,
+ (int)old_lm_hash_enc.length);
+ old_lm_hash_enc = data_blob(NULL, 0);
+ }
+ } else if (strequal(request, "nt-domain")) {
+ domain = smb_xstrdup(parameter);
+ } else if(strequal(request, "username")) {
+ username = smb_xstrdup(parameter);
+ } else if(strequal(request, "full-username")) {
+ username = smb_xstrdup(parameter);
+ } else if(strequal(request, "new-password")) {
+ newpswd = smb_xstrdup(parameter);
+ } else if (strequal(request, "old-password")) {
+ oldpswd = smb_xstrdup(parameter);
+ } else {
+ x_fprintf(x_stdout, "Error: Unknown request %s\n.\n", request);
+ }
+}
+
static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn)
{
char buf[SQUID_BUFFER_SIZE+1];
@@ -1597,7 +2063,7 @@ static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helpe
exit(0);
}
- c=memchr(buf,'\n',sizeof(buf)-1);
+ c=(char *)memchr(buf,'\n',sizeof(buf)-1);
if (c) {
*c = '\0';
length = c-buf;
@@ -1709,7 +2175,8 @@ enum {
OPT_LM_KEY,
OPT_USER_SESSION_KEY,
OPT_DIAGNOSTICS,
- OPT_REQUIRE_MEMBERSHIP
+ OPT_REQUIRE_MEMBERSHIP,
+ OPT_USE_CACHED_CREDS
};
int main(int argc, const char **argv)
@@ -1744,6 +2211,7 @@ enum {
{ "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"},
{ "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retrieve LM session key"},
{ "request-nt-key", 0, POPT_ARG_NONE, &request_user_session_key, OPT_USER_SESSION_KEY, "Retrieve User (NT) session key"},
+ { "use-cached-creds", 0, POPT_ARG_NONE, &use_cached_creds, OPT_USE_CACHED_CREDS, "Use cached credentials if no password is given"},
{ "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"},
{ "require-membership-of", 0, POPT_ARG_STRING, &require_membership_of, OPT_REQUIRE_MEMBERSHIP, "Require that a user be a member of this group (either name or SID) for authentication to succeed" },
POPT_COMMON_SAMBA
diff --git a/source/utils/ntlm_auth_diagnostics.c b/source/utils/ntlm_auth_diagnostics.c
index c8ea966a558..f7997de711e 100644
--- a/source/utils/ntlm_auth_diagnostics.c
+++ b/source/utils/ntlm_auth_diagnostics.c
@@ -445,10 +445,11 @@ static BOOL test_plaintext(enum ntlm_break break_which)
DATA_BLOB nt_response = data_blob(NULL, 0);
DATA_BLOB lm_response = data_blob(NULL, 0);
char *password;
+ smb_ucs2_t *nt_response_ucs2;
uchar user_session_key[16];
uchar lm_key[16];
- static const uchar zeros[8];
+ static const uchar zeros[8] = { 0, };
DATA_BLOB chall = data_blob(zeros, sizeof(zeros));
char *error_string;
@@ -457,12 +458,13 @@ static BOOL test_plaintext(enum ntlm_break break_which)
flags |= WBFLAG_PAM_LMKEY;
flags |= WBFLAG_PAM_USER_SESSION_KEY;
- if ((push_ucs2_allocate((smb_ucs2_t **)&nt_response.data, opt_password)) == -1) {
+ if ((push_ucs2_allocate(&nt_response_ucs2, opt_password)) == -1) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
exit(1);
}
- nt_response.length = strlen_w(((void *)nt_response.data))*sizeof(smb_ucs2_t);
+ nt_response.data = (unsigned char *)nt_response_ucs2;
+ nt_response.length = strlen_w(nt_response_ucs2)*sizeof(smb_ucs2_t);
if ((password = strdup_upper(opt_password)) == NULL) {
DEBUG(0, ("strdup_upper failed!\n"));
@@ -472,7 +474,7 @@ static BOOL test_plaintext(enum ntlm_break break_which)
if ((convert_string_allocate(NULL, CH_UNIX,
CH_DOS, password,
strlen(password)+1,
- (void**)&lm_response.data,True)) == -1) {
+ &lm_response.data,True)) == -1) {
DEBUG(0, ("convert_string_allocate failed!\n"));
exit(1);
}
diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c
index 0a6fb7e8bec..d79ab187a3b 100644
--- a/source/utils/pdbedit.c
+++ b/source/utils/pdbedit.c
@@ -176,11 +176,6 @@ static int reinit_account_policies (void)
}
}
- if (!remove_account_policy_migrated()) {
- fprintf(stderr, "Can't remove marker from tdb\n");
- return -1;
- }
-
return 0;
}
@@ -193,11 +188,6 @@ static int export_account_policies (struct pdb_methods *in, struct pdb_methods *
{
int i;
- if (!account_policy_migrated(True)) {
- fprintf(stderr, "Unable to set account policy marker in tdb\n");
- return -1;
- }
-
for ( i=1; decode_account_policy_name(i) != NULL; i++ ) {
uint32 policy_value;
NTSTATUS status;
@@ -206,7 +196,6 @@ static int export_account_policies (struct pdb_methods *in, struct pdb_methods *
if ( NT_STATUS_IS_ERR(status) ) {
fprintf(stderr, "Unable to get account policy from %s\n", in->name);
- remove_account_policy_migrated();
return -1;
}
@@ -214,7 +203,6 @@ static int export_account_policies (struct pdb_methods *in, struct pdb_methods *
if ( NT_STATUS_IS_ERR(status) ) {
fprintf(stderr, "Unable to migrate account policy to %s\n", out->name);
- remove_account_policy_migrated();
return -1;
}
}
@@ -419,8 +407,7 @@ static int set_user_info (struct pdb_methods *in, const char *username,
const char *drive, const char *script,
const char *profile, const char *account_control,
const char *user_sid, const char *user_domain,
- const BOOL badpw, const BOOL hours,
- time_t pwd_can_change, time_t pwd_must_change)
+ const BOOL badpw, const BOOL hours)
{
BOOL updated_autolock = False, updated_badpw = False;
struct samu *sam_pwent=NULL;
@@ -447,14 +434,6 @@ static int set_user_info (struct pdb_methods *in, const char *username,
pdb_set_hours(sam_pwent, hours_array, PDB_CHANGED);
}
- if (pwd_can_change != -1) {
- pdb_set_pass_can_change_time(sam_pwent, pwd_can_change, PDB_CHANGED);
- }
-
- if (pwd_must_change != -1) {
- pdb_set_pass_must_change_time(sam_pwent, pwd_must_change, PDB_CHANGED);
- }
-
if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) {
DEBUG(2,("pdb_update_autolock_flag failed.\n"));
}
@@ -778,8 +757,6 @@ int main (int argc, char **argv)
BOOL account_policy_value_set = False;
static BOOL badpw_reset = False;
static BOOL hours_reset = False;
- static char *pwd_can_change_time = NULL;
- static char *pwd_must_change_time = NULL;
static char *pwd_time_format = NULL;
static BOOL pw_from_stdin = False;
struct pdb_methods *bin, *bout, *bdef;
@@ -814,14 +791,18 @@ int main (int argc, char **argv)
{"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL},
{"bad-password-count-reset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
{"logon-hours-reset", 'Z', POPT_ARG_NONE, &hours_reset, 0, "reset logon hours", NULL},
- {"pwd-can-change-time", 0, POPT_ARG_STRING, &pwd_can_change_time, 0, "Set password can change time (unix time in seconds since 1970 if time format not provided)", NULL },
- {"pwd-must-change-time", 0, POPT_ARG_STRING, &pwd_must_change_time, 0, "Set password must change time (unix time in seconds since 1970 if time format not provided)", NULL },
{"time-format", 0, POPT_ARG_STRING, &pwd_time_format, 0, "The time format for time parameters", NULL },
{"password-from-stdin", 't', POPT_ARG_NONE, &pw_from_stdin, 0, "get password from standard in", NULL},
POPT_COMMON_SAMBA
POPT_TABLEEND
};
+ /* we shouldn't have silly checks like this */
+ if (getuid() != 0) {
+ d_fprintf(stderr, "You must be root to use pdbedit\n");
+ return -1;
+ }
+
bin = bout = bdef = NULL;
load_case_tables();
@@ -878,9 +859,7 @@ int main (int argc, char **argv)
(backend_in ? BIT_IMPORT : 0) +
(backend_out ? BIT_EXPORT : 0) +
(badpw_reset ? BIT_BADPWRESET : 0) +
- (hours_reset ? BIT_LOGONHOURS : 0) +
- (pwd_can_change_time ? BIT_CAN_CHANGE: 0) +
- (pwd_must_change_time ? BIT_MUST_CHANGE: 0);
+ (hours_reset ? BIT_LOGONHOURS : 0);
if (setparms & BIT_BACKEND) {
if (!NT_STATUS_IS_OK(make_pdb_method_name( &bdef, backend ))) {
@@ -906,12 +885,18 @@ int main (int argc, char **argv)
uint32 value;
int field = account_policy_name_to_fieldnum(account_policy);
if (field == 0) {
- char *apn = account_policy_names_list();
- fprintf(stderr, "No account policy by that name\n");
- if (apn) {
- fprintf(stderr, "Account policy names are :\n%s\n", apn);
+ const char **names;
+ int count;
+ int i;
+ account_policy_names_list(&names, &count);
+ fprintf(stderr, "No account policy by that name!\n");
+ if (count !=0) {
+ fprintf(stderr, "Account policy names are:\n");
+ for (i = 0; i < count ; i++) {
+ d_fprintf(stderr, "%s\n", names[i]);
+ }
}
- SAFE_FREE(apn);
+ SAFE_FREE(names);
exit(1);
}
if (!pdb_get_account_policy(field, &value)) {
@@ -1052,67 +1037,9 @@ int main (int argc, char **argv)
/* account modification operations */
if (!(checkparms & ~(BIT_MODIFY + BIT_USER))) {
- time_t pwd_can_change = -1;
- time_t pwd_must_change = -1;
- const char *errstr;
-
- if (pwd_can_change_time) {
- errstr = "can";
- if (pwd_time_format) {
- struct tm tm;
- char *ret;
-
- memset(&tm, 0, sizeof(struct tm));
- ret = strptime(pwd_can_change_time, pwd_time_format, &tm);
- if (ret == NULL || *ret != '\0') {
- goto error;
- }
-
- pwd_can_change = mktime(&tm);
-
- if (pwd_can_change == -1) {
- goto error;
- }
- } else { /* assume it is unix time */
- errno = 0;
- pwd_can_change = strtol(pwd_can_change_time, NULL, 10);
- if (errno) {
- goto error;
- }
- }
- }
- if (pwd_must_change_time) {
- errstr = "must";
- if (pwd_time_format) {
- struct tm tm;
- char *ret;
-
- memset(&tm, 0, sizeof(struct tm));
- ret = strptime(pwd_must_change_time, pwd_time_format, &tm);
- if (ret == NULL || *ret != '\0') {
- goto error;
- }
-
- pwd_must_change = mktime(&tm);
-
- if (pwd_must_change == -1) {
- goto error;
- }
- } else { /* assume it is unix time */
- errno = 0;
- pwd_must_change = strtol(pwd_must_change_time, NULL, 10);
- if (errno) {
- goto error;
- }
- }
- }
return set_user_info (bdef, user_name, full_name, home_dir,
acct_desc, home_drive, logon_script, profile_path, account_control,
- user_sid, user_domain, badpw_reset, hours_reset, pwd_can_change,
- pwd_must_change);
-error:
- fprintf (stderr, "Error parsing the time in pwd-%s-change-time!\n", errstr);
- return -1;
+ user_sid, user_domain, badpw_reset, hours_reset);
}
}
diff --git a/source/utils/profiles.c b/source/utils/profiles.c
index d40a2deea3b..3a5c8f517c9 100644
--- a/source/utils/profiles.c
+++ b/source/utils/profiles.c
@@ -27,34 +27,85 @@
DOM_SID old_sid, new_sid;
int change = 0, new_val = 0;
+BOOL opt_verbose = False;
+/********************************************************************
+********************************************************************/
+
+static void verbose_output(const char *format, ...) PRINTF_ATTRIBUTE(1,2);
+static void verbose_output(const char *format, ...)
+{
+ va_list args;
+ char *var = NULL;
+
+ if (!opt_verbose) {
+ return;
+ }
+
+ va_start(args, format);
+ if ((vasprintf(&var, format, args)) == -1) {
+ va_end(args);
+ return;
+ }
+
+ fprintf(stdout, var);
+ va_end(args);
+ SAFE_FREE(var);
+}
/********************************************************************
********************************************************************/
static BOOL swap_sid_in_acl( SEC_DESC *sd, DOM_SID *s1, DOM_SID *s2 )
{
- SEC_ACL *acl = sd->dacl;
+ SEC_ACL *acl;
int i;
BOOL update = False;
+ verbose_output(" Owner SID: %s\n", sid_string_static(sd->owner_sid));
if ( sid_equal( sd->owner_sid, s1 ) ) {
sid_copy( sd->owner_sid, s2 );
update = True;
+ verbose_output(" New Owner SID: %s\n",
+ sid_string_static(sd->owner_sid));
+
}
- if ( sid_equal( sd->grp_sid, s1 ) ) {
- sid_copy( sd->grp_sid, s2 );
+ verbose_output(" Group SID: %s\n", sid_string_static(sd->group_sid));
+ if ( sid_equal( sd->group_sid, s1 ) ) {
+ sid_copy( sd->group_sid, s2 );
update = True;
+ verbose_output(" New Group SID: %s\n",
+ sid_string_static(sd->group_sid));
}
+ acl = sd->dacl;
+ verbose_output(" DACL: %d entries:\n", acl->num_aces);
for ( i=0; i<acl->num_aces; i++ ) {
- if ( sid_equal( &acl->ace[i].trustee, s1 ) ) {
- sid_copy( &acl->ace[i].trustee, s2 );
+ verbose_output(" Trustee SID: %s\n",
+ sid_string_static(&acl->aces[i].trustee));
+ if ( sid_equal( &acl->aces[i].trustee, s1 ) ) {
+ sid_copy( &acl->aces[i].trustee, s2 );
update = True;
+ verbose_output(" New Trustee SID: %s\n",
+ sid_string_static(&acl->aces[i].trustee));
}
}
+#if 0
+ acl = sd->sacl;
+ verbose_output(" SACL: %d entries: \n", acl->num_aces);
+ for ( i=0; i<acl->num_aces; i++ ) {
+ verbose_output(" Trustee SID: %s\n",
+ sid_string_static(&acl->aces[i].trustee));
+ if ( sid_equal( &acl->aces[i].trustee, s1 ) ) {
+ sid_copy( &acl->aces[i].trustee, s2 );
+ update = True;
+ verbose_output(" New Trustee SID: %s\n",
+ sid_string_static(&acl->aces[i].trustee));
+ }
+ }
+#endif
return update;
}
@@ -79,8 +130,8 @@ static BOOL copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
return False;
}
- if ( swap_sid_in_acl( new_sd, &old_sid, &new_sid ) )
- DEBUG(2,("Updating ACL for %s\n", nk->keyname ));
+ verbose_output("ACL for %s%s%s\n", parentpath, parent ? "\\" : "", nk->keyname);
+ swap_sid_in_acl( new_sd, &old_sid, &new_sid );
if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
DEBUG(0,("copy_registry_tree: talloc() failure!\n"));
@@ -121,7 +172,7 @@ static BOOL copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
TALLOC_FREE( subkeys );
- DEBUG(1,("[%s]\n", path));
+ verbose_output("[%s]\n", path);
return True;
}
@@ -139,6 +190,7 @@ int main( int argc, char *argv[] )
POPT_AUTOHELP
{ "change-sid", 'c', POPT_ARG_STRING, NULL, 'c', "Provides SID to change" },
{ "new-sid", 'n', POPT_ARG_STRING, NULL, 'n', "Provides SID to change to" },
+ { "verbose", 'v', POPT_ARG_NONE, &opt_verbose, 'v', "Verbose output" },
POPT_COMMON_SAMBA
POPT_COMMON_VERSION
POPT_TABLEEND
diff --git a/source/utils/sharesec.c b/source/utils/sharesec.c
new file mode 100644
index 00000000000..4fa948a18a5
--- /dev/null
+++ b/source/utils/sharesec.c
@@ -0,0 +1,607 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * Utility for managing share permissions
+ *
+ * Copyright (C) Tim Potter 2000
+ * Copyright (C) Jeremy Allison 2000
+ * Copyright (C) Jelmer Vernooij 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
+ * 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 TALLOC_CTX *ctx;
+
+enum acl_mode {SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD, SMB_ACL_SET, SMB_ACL_VIEW };
+
+struct perm_value {
+ const char *perm;
+ uint32 mask;
+};
+
+/* These values discovered by inspection */
+
+static const struct perm_value special_values[] = {
+ { "R", SEC_RIGHTS_FILE_READ },
+ { "W", SEC_RIGHTS_FILE_WRITE },
+ { "X", SEC_RIGHTS_FILE_EXECUTE },
+ { "D", SEC_STD_DELETE },
+ { "P", SEC_STD_WRITE_DAC },
+ { "O", SEC_STD_WRITE_OWNER },
+ { NULL, 0 },
+};
+
+#define SEC_RIGHTS_DIR_CHANGE ( SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE )
+
+static const struct perm_value standard_values[] = {
+ { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
+ { "CHANGE", SEC_RIGHTS_DIR_CHANGE },
+ { "FULL", SEC_RIGHTS_DIR_ALL },
+ { NULL, 0 },
+};
+
+/********************************************************************
+ print an ACE on a FILE
+********************************************************************/
+
+static void print_ace(FILE *f, SEC_ACE *ace)
+{
+ const struct perm_value *v;
+ int do_print = 0;
+ uint32 got_mask;
+
+ fprintf(f, "%s:", sid_string_static(&ace->trustee));
+
+ /* Ace type */
+
+ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
+ fprintf(f, "ALLOWED");
+ } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ fprintf(f, "DENIED");
+ } else {
+ fprintf(f, "%d", ace->type);
+ }
+
+ /* Not sure what flags can be set in a file ACL */
+
+ fprintf(f, "/%d/", ace->flags);
+
+ /* Standard permissions */
+
+ for (v = standard_values; v->perm; v++) {
+ if (ace->access_mask == v->mask) {
+ fprintf(f, "%s", v->perm);
+ return;
+ }
+ }
+
+ /* Special permissions. Print out a hex value if we have
+ leftover bits in the mask. */
+
+ got_mask = ace->access_mask;
+
+ again:
+ for (v = special_values; v->perm; v++) {
+ if ((ace->access_mask & v->mask) == v->mask) {
+ if (do_print) {
+ fprintf(f, "%s", v->perm);
+ }
+ got_mask &= ~v->mask;
+ }
+ }
+
+ if (!do_print) {
+ if (got_mask != 0) {
+ fprintf(f, "0x%08x", ace->access_mask);
+ } else {
+ do_print = 1;
+ goto again;
+ }
+ }
+}
+
+/********************************************************************
+ print a ascii version of a security descriptor on a FILE handle
+********************************************************************/
+
+static void sec_desc_print(FILE *f, SEC_DESC *sd)
+{
+ uint32 i;
+
+ fprintf(f, "REVISION:%d\n", sd->revision);
+
+ /* Print owner and group sid */
+
+ fprintf(f, "OWNER:%s\n", sid_string_static(sd->owner_sid));
+
+ fprintf(f, "GROUP:%s\n", sid_string_static(sd->group_sid));
+
+ /* Print aces */
+ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+ SEC_ACE *ace = &sd->dacl->aces[i];
+ fprintf(f, "ACL:");
+ print_ace(f, ace);
+ fprintf(f, "\n");
+ }
+
+}
+
+/********************************************************************
+ parse an ACE in the same format as print_ace()
+********************************************************************/
+
+static BOOL parse_ace(SEC_ACE *ace, const char *orig_str)
+{
+ char *p;
+ const char *cp;
+ fstring tok;
+ unsigned int atype = 0;
+ unsigned int aflags = 0;
+ unsigned int amask = 0;
+ DOM_SID sid;
+ SEC_ACCESS mask;
+ const struct perm_value *v;
+ char *str = SMB_STRDUP(orig_str);
+
+ if (!str) {
+ return False;
+ }
+
+ ZERO_STRUCTP(ace);
+ p = strchr_m(str,':');
+ if (!p) {
+ printf("ACE '%s': missing ':'.\n", orig_str);
+ SAFE_FREE(str);
+ return False;
+ }
+ *p = '\0';
+ p++;
+ /* Try to parse numeric form */
+
+ if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
+ string_to_sid(&sid, str)) {
+ goto done;
+ }
+
+ /* Try to parse text form */
+
+ if (!string_to_sid(&sid, str)) {
+ printf("ACE '%s': failed to convert '%s' to SID\n",
+ orig_str, str);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ cp = p;
+ if (!next_token(&cp, tok, "/", sizeof(fstring))) {
+ printf("ACE '%s': failed to find '/' character.\n",
+ orig_str);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
+ atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
+ atype = SEC_ACE_TYPE_ACCESS_DENIED;
+ } else {
+ printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ /* Only numeric form accepted for flags at present */
+ /* no flags on share permissions */
+
+ if (!(next_token(&cp, tok, "/", sizeof(fstring)) &&
+ sscanf(tok, "%i", &aflags) && aflags == 0)) {
+ printf("ACE '%s': bad integer flags entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ if (!next_token(&cp, tok, "/", sizeof(fstring))) {
+ printf("ACE '%s': missing / at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ if (strncmp(tok, "0x", 2) == 0) {
+ if (sscanf(tok, "%i", &amask) != 1) {
+ printf("ACE '%s': bad hex number at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ return False;
+ }
+ goto done;
+ }
+
+ for (v = standard_values; v->perm; v++) {
+ if (strcmp(tok, v->perm) == 0) {
+ amask = v->mask;
+ goto done;
+ }
+ }
+
+ p = tok;
+
+ while(*p) {
+ BOOL found = False;
+
+ for (v = special_values; v->perm; v++) {
+ if (v->perm[0] == *p) {
+ amask |= v->mask;
+ found = True;
+ }
+ }
+
+ if (!found) {
+ printf("ACE '%s': bad permission value at '%s'\n",
+ orig_str, p);
+ SAFE_FREE(str);
+ return False;
+ }
+ p++;
+ }
+
+ if (*p) {
+ SAFE_FREE(str);
+ return False;
+ }
+
+ done:
+ mask = amask;
+ init_sec_ace(ace, &sid, atype, mask, aflags);
+ SAFE_FREE(str);
+ return True;
+}
+
+
+/********************************************************************
+********************************************************************/
+
+static SEC_DESC* parse_acl_string(TALLOC_CTX *mem_ctx, const char *szACL, size_t *sd_size )
+{
+ SEC_DESC *sd = NULL;
+ SEC_ACE *ace;
+ SEC_ACL *acl;
+ int num_ace;
+ const char *pacl;
+ int i;
+
+ if ( !szACL )
+ return NULL;
+
+ pacl = szACL;
+ num_ace = count_chars( pacl, ',' ) + 1;
+
+ if ( !(ace = TALLOC_ZERO_ARRAY( mem_ctx, SEC_ACE, num_ace )) )
+ return NULL;
+
+ for ( i=0; i<num_ace; i++ ) {
+ char *end_acl = strchr_m( pacl, ',' );
+ fstring acl_string;
+
+ strncpy( acl_string, pacl, MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1) );
+ acl_string[MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1)] = '\0';
+
+ if ( !parse_ace( &ace[i], acl_string ) )
+ return NULL;
+
+ pacl = end_acl;
+ pacl++;
+ }
+
+ if ( !(acl = make_sec_acl( mem_ctx, NT4_ACL_REVISION, num_ace, ace )) )
+ return NULL;
+
+ sd = make_sec_desc( mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
+ NULL, NULL, NULL, acl, sd_size);
+
+ return sd;
+}
+
+/* add an ACE to a list of ACEs in a SEC_ACL */
+static BOOL add_ace(TALLOC_CTX *mem_ctx, SEC_ACL **the_acl, SEC_ACE *ace)
+{
+ SEC_ACL *new_ace;
+ SEC_ACE *aces;
+ if (! *the_acl) {
+ return (((*the_acl) = make_sec_acl(mem_ctx, 3, 1, ace)) != NULL);
+ }
+
+ if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) {
+ return False;
+ }
+ memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
+ memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
+ new_ace = make_sec_acl(mem_ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
+ SAFE_FREE(aces);
+ (*the_acl) = new_ace;
+ return True;
+}
+
+/* The MSDN is contradictory over the ordering of ACE entries in an ACL.
+ However NT4 gives a "The information may have been modified by a
+ computer running Windows NT 5.0" if denied ACEs do not appear before
+ allowed ACEs. */
+
+static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
+{
+ if (sec_ace_equal(ace1, ace2))
+ return 0;
+
+ if (ace1->type != ace2->type)
+ return ace2->type - ace1->type;
+
+ if (sid_compare(&ace1->trustee, &ace2->trustee))
+ return sid_compare(&ace1->trustee, &ace2->trustee);
+
+ if (ace1->flags != ace2->flags)
+ return ace1->flags - ace2->flags;
+
+ if (ace1->access_mask != ace2->access_mask)
+ return ace1->access_mask - ace2->access_mask;
+
+ if (ace1->size != ace2->size)
+ return ace1->size - ace2->size;
+
+ return memcmp(ace1, ace2, sizeof(SEC_ACE));
+}
+
+static void sort_acl(SEC_ACL *the_acl)
+{
+ uint32 i;
+ if (!the_acl) return;
+
+ qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare);
+
+ for (i=1;i<the_acl->num_aces;) {
+ if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
+ int j;
+ for (j=i; j<the_acl->num_aces-1; j++) {
+ the_acl->aces[j] = the_acl->aces[j+1];
+ }
+ the_acl->num_aces--;
+ } else {
+ i++;
+ }
+ }
+}
+
+
+static int change_share_sec(TALLOC_CTX *mem_ctx, const char *sharename, char *the_acl, enum acl_mode mode)
+{
+ SEC_DESC *sd;
+ SEC_DESC *old = NULL;
+ size_t sd_size = 0;
+ uint32 i, j;
+
+ if (mode != SMB_ACL_SET) {
+ if (!(old = get_share_security( mem_ctx, sharename, &sd_size )) ) {
+ fprintf(stderr, "Unable to retrieve permissions for share [%s]\n", sharename);
+ return -1;
+ }
+ }
+
+ if ( (mode != SMB_ACL_VIEW) && !(sd = parse_acl_string(mem_ctx, the_acl, &sd_size )) ) {
+ fprintf( stderr, "Failed to parse acl\n");
+ return -1;
+ }
+
+ switch (mode) {
+ case SMB_ACL_VIEW:
+ sec_desc_print( stdout, old);
+ return 0;
+ case SMB_ACL_DELETE:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ BOOL found = False;
+
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sec_ace_equal(&sd->dacl->aces[i], &old->dacl->aces[j])) {
+ uint32 k;
+ for (k=j; k<old->dacl->num_aces-1;k++) {
+ old->dacl->aces[k] = old->dacl->aces[k+1];
+ }
+ old->dacl->num_aces--;
+ found = True;
+ break;
+ }
+ }
+
+ if (!found) {
+ printf("ACL for ACE:");
+ print_ace(stdout, &sd->dacl->aces[i]);
+ printf(" not found\n");
+ }
+ }
+
+ break;
+ case SMB_ACL_MODIFY:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ BOOL found = False;
+
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sid_equal(&sd->dacl->aces[i].trustee,
+ &old->dacl->aces[j].trustee)) {
+ old->dacl->aces[j] = sd->dacl->aces[i];
+ found = True;
+ }
+ }
+
+ if (!found) {
+ printf("ACL for SID %s not found\n", sid_string_static(&sd->dacl->aces[i].trustee));
+ }
+ }
+
+ if (sd->owner_sid) {
+ old->owner_sid = sd->owner_sid;
+ }
+
+ if (sd->group_sid) {
+ old->group_sid = sd->group_sid;
+ }
+ break;
+ case SMB_ACL_ADD:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ add_ace(mem_ctx, &old->dacl, &sd->dacl->aces[i]);
+ }
+ break;
+ case SMB_ACL_SET:
+ old = sd;
+ break;
+ }
+
+ /* Denied ACE entries must come before allowed ones */
+ sort_acl(old->dacl);
+
+ if ( !set_share_security( sharename, old ) ) {
+ fprintf( stderr, "Failed to store acl for share [%s]\n", sharename );
+ return 2;
+ }
+ return 0;
+}
+
+/********************************************************************
+ main program
+********************************************************************/
+
+int main(int argc, const char *argv[])
+{
+ int opt;
+ int retval = 0;
+ enum acl_mode mode = SMB_ACL_SET;
+ static char *the_acl = NULL;
+ fstring sharename;
+ BOOL force_acl = False;
+ int snum;
+ poptContext pc;
+ BOOL initialize_sid = False;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "remove", 'r', POPT_ARG_STRING, &the_acl, 'r', "Delete an ACE", "ACL" },
+ { "modify", 'm', POPT_ARG_STRING, &the_acl, 'm', "Modify an acl", "ACL" },
+ { "add", 'a', POPT_ARG_STRING, &the_acl, 'a', "Add an ACE", "ACL" },
+ { "replace", 'R', POPT_ARG_STRING, &the_acl, 'R', "Set share mission ACL", "ACLS" },
+ { "view", 'v', POPT_ARG_NONE, NULL, 'v', "View current share permissions" },
+ { "machine-sid", 'M', POPT_ARG_NONE, NULL, 'M', "Initialize the machine SID" },
+ { "force", 'F', POPT_ARG_NONE, NULL, 'F', "Force storing the ACL", "ACLS" },
+ POPT_COMMON_SAMBA
+ { NULL }
+ };
+
+ if ( !(ctx = talloc_init("main")) ) {
+ fprintf( stderr, "Failed to initialize talloc context!\n");
+ return -1;
+ }
+
+ /* set default debug level to 1 regardless of what smb.conf sets */
+ setup_logging( "sharesec", True );
+ DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
+ dbf = x_stderr;
+ x_setbuf( x_stderr, NULL );
+
+ pc = poptGetContext("sharesec", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "sharename\n");
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'r':
+ the_acl = smb_xstrdup(poptGetOptArg(pc));
+ mode = SMB_ACL_DELETE;
+ break;
+
+ case 'm':
+ the_acl = smb_xstrdup(poptGetOptArg(pc));
+ mode = SMB_ACL_MODIFY;
+ break;
+
+ case 'a':
+ the_acl = smb_xstrdup(poptGetOptArg(pc));
+ mode = SMB_ACL_ADD;
+ break;
+ case 'R':
+ the_acl = smb_xstrdup(poptGetOptArg(pc));
+ mode = SMB_ACL_SET;
+ break;
+
+ case 'v':
+ mode = SMB_ACL_VIEW;
+ break;
+
+ case 'F':
+ force_acl = True;
+ break;
+
+ case 'M':
+ initialize_sid = True;
+ break;
+ }
+ }
+
+ setlinebuf(stdout);
+
+ load_case_tables();
+
+ lp_load( dyn_CONFIGFILE, False, False, False, True );
+
+ /* check for initializing secrets.tdb first */
+
+ if ( initialize_sid ) {
+ DOM_SID *sid = get_global_sam_sid();
+
+ if ( !sid ) {
+ fprintf( stderr, "Failed to retrieve Machine SID!\n");
+ return 3;
+ }
+
+ printf ("%s\n", sid_string_static( sid ) );
+ return 0;
+ }
+
+ if ( mode == SMB_ACL_VIEW && force_acl ) {
+ fprintf( stderr, "Invalid combination of -F and -v\n");
+ return -1;
+ }
+
+ /* get the sharename */
+
+ if(!poptPeekArg(pc)) {
+ poptPrintUsage(pc, stderr, 0);
+ return -1;
+ }
+
+ fstrcpy(sharename, poptGetArg(pc));
+
+ snum = lp_servicenumber( sharename );
+
+ if ( snum == -1 && !force_acl ) {
+ fprintf( stderr, "Invalid sharename: %s\n", sharename);
+ return -1;
+ }
+
+ retval = change_share_sec(ctx, sharename, the_acl, mode);
+
+ talloc_destroy(ctx);
+
+ return retval;
+}
diff --git a/source/utils/smbcacls.c b/source/utils/smbcacls.c
index b31fd95f7ab..82cae037207 100644
--- a/source/utils/smbcacls.c
+++ b/source/utils/smbcacls.c
@@ -108,7 +108,7 @@ static void SidToString(fstring str, DOM_SID *sid)
{
char **domains = NULL;
char **names = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
sid_to_string(str, sid);
@@ -135,7 +135,7 @@ static void SidToString(fstring str, DOM_SID *sid)
/* convert a string to a SID, either numeric or username/group */
static BOOL StringToSid(DOM_SID *sid, const char *str)
{
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
DOM_SID *sids = NULL;
BOOL result = True;
@@ -172,7 +172,7 @@ static void print_ace(FILE *f, SEC_ACE *ace)
if (numeric) {
fprintf(f, "%d/%d/0x%08x",
- ace->type, ace->flags, ace->info.mask);
+ ace->type, ace->flags, ace->access_mask);
return;
}
@@ -193,7 +193,7 @@ static void print_ace(FILE *f, SEC_ACE *ace)
/* Standard permissions */
for (v = standard_values; v->perm; v++) {
- if (ace->info.mask == v->mask) {
+ if (ace->access_mask == v->mask) {
fprintf(f, "%s", v->perm);
return;
}
@@ -202,11 +202,11 @@ static void print_ace(FILE *f, SEC_ACE *ace)
/* Special permissions. Print out a hex value if we have
leftover bits in the mask. */
- got_mask = ace->info.mask;
+ got_mask = ace->access_mask;
again:
for (v = special_values; v->perm; v++) {
- if ((ace->info.mask & v->mask) == v->mask) {
+ if ((ace->access_mask & v->mask) == v->mask) {
if (do_print) {
fprintf(f, "%s", v->perm);
}
@@ -216,7 +216,7 @@ static void print_ace(FILE *f, SEC_ACE *ace)
if (!do_print) {
if (got_mask != 0) {
- fprintf(f, "0x%08x", ace->info.mask);
+ fprintf(f, "0x%08x", ace->access_mask);
} else {
do_print = 1;
goto again;
@@ -348,7 +348,7 @@ static BOOL parse_ace(SEC_ACE *ace, const char *orig_str)
}
done:
- mask.mask = amask;
+ mask = amask;
init_sec_ace(ace, &sid, atype, mask, aflags);
SAFE_FREE(str);
return True;
@@ -366,7 +366,7 @@ static BOOL add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) {
return False;
}
- memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE));
+ memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
new_ace = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
SAFE_FREE(aces);
@@ -381,7 +381,7 @@ static SEC_DESC *sec_desc_parse(char *str)
fstring tok;
SEC_DESC *ret = NULL;
size_t sd_size;
- DOM_SID *grp_sid=NULL, *owner_sid=NULL;
+ DOM_SID *group_sid=NULL, *owner_sid=NULL;
SEC_ACL *dacl=NULL;
int revision=1;
@@ -407,13 +407,13 @@ static SEC_DESC *sec_desc_parse(char *str)
}
if (strncmp(tok,"GROUP:", 6) == 0) {
- if (grp_sid) {
+ if (group_sid) {
printf("Only specify group once\n");
goto done;
}
- grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
- if (!grp_sid ||
- !StringToSid(grp_sid, tok+6)) {
+ group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
+ if (!group_sid ||
+ !StringToSid(group_sid, tok+6)) {
printf("Failed to parse group sid\n");
goto done;
}
@@ -436,11 +436,11 @@ static SEC_DESC *sec_desc_parse(char *str)
goto done;
}
- ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid,
+ ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, group_sid,
NULL, dacl, &sd_size);
done:
- SAFE_FREE(grp_sid);
+ SAFE_FREE(group_sid);
SAFE_FREE(owner_sid);
return ret;
@@ -465,8 +465,8 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd)
fprintf(f, "OWNER:%s\n", sidstr);
- if (sd->grp_sid) {
- SidToString(sidstr, sd->grp_sid);
+ if (sd->group_sid) {
+ SidToString(sidstr, sd->group_sid);
} else {
fstrcpy(sidstr, "");
}
@@ -475,7 +475,7 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd)
/* Print aces */
for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
- SEC_ACE *ace = &sd->dacl->ace[i];
+ SEC_ACE *ace = &sd->dacl->aces[i];
fprintf(f, "ACL:");
print_ace(f, ace);
fprintf(f, "\n");
@@ -593,8 +593,8 @@ static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
if (ace1->flags != ace2->flags)
return ace1->flags - ace2->flags;
- if (ace1->info.mask != ace2->info.mask)
- return ace1->info.mask - ace2->info.mask;
+ if (ace1->access_mask != ace2->access_mask)
+ return ace1->access_mask - ace2->access_mask;
if (ace1->size != ace2->size)
return ace1->size - ace2->size;
@@ -607,13 +607,13 @@ static void sort_acl(SEC_ACL *the_acl)
uint32 i;
if (!the_acl) return;
- qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), QSORT_CAST ace_compare);
+ qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare);
for (i=1;i<the_acl->num_aces;) {
- if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) {
+ if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
int j;
for (j=i; j<the_acl->num_aces-1; j++) {
- the_acl->ace[j] = the_acl->ace[j+1];
+ the_acl->aces[j] = the_acl->aces[j+1];
}
the_acl->num_aces--;
} else {
@@ -665,11 +665,11 @@ static int cacl_set(struct cli_state *cli, char *filename,
BOOL found = False;
for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
- if (sec_ace_equal(&sd->dacl->ace[i],
- &old->dacl->ace[j])) {
+ if (sec_ace_equal(&sd->dacl->aces[i],
+ &old->dacl->aces[j])) {
uint32 k;
for (k=j; k<old->dacl->num_aces-1;k++) {
- old->dacl->ace[k] = old->dacl->ace[k+1];
+ old->dacl->aces[k] = old->dacl->aces[k+1];
}
old->dacl->num_aces--;
found = True;
@@ -679,7 +679,7 @@ static int cacl_set(struct cli_state *cli, char *filename,
if (!found) {
printf("ACL for ACE:");
- print_ace(stdout, &sd->dacl->ace[i]);
+ print_ace(stdout, &sd->dacl->aces[i]);
printf(" not found\n");
}
}
@@ -690,9 +690,9 @@ static int cacl_set(struct cli_state *cli, char *filename,
BOOL found = False;
for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
- if (sid_equal(&sd->dacl->ace[i].trustee,
- &old->dacl->ace[j].trustee)) {
- old->dacl->ace[j] = sd->dacl->ace[i];
+ if (sid_equal(&sd->dacl->aces[i].trustee,
+ &old->dacl->aces[j].trustee)) {
+ old->dacl->aces[j] = sd->dacl->aces[i];
found = True;
}
}
@@ -700,7 +700,7 @@ static int cacl_set(struct cli_state *cli, char *filename,
if (!found) {
fstring str;
- SidToString(str, &sd->dacl->ace[i].trustee);
+ SidToString(str, &sd->dacl->aces[i].trustee);
printf("ACL for SID %s not found\n", str);
}
}
@@ -709,15 +709,15 @@ static int cacl_set(struct cli_state *cli, char *filename,
old->owner_sid = sd->owner_sid;
}
- if (sd->grp_sid) {
- old->grp_sid = sd->grp_sid;
+ if (sd->group_sid) {
+ old->group_sid = sd->group_sid;
}
break;
case SMB_ACL_ADD:
for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
- add_ace(&old->dacl, &sd->dacl->ace[i]);
+ add_ace(&old->dacl, &sd->dacl->aces[i]);
}
break;
@@ -738,7 +738,7 @@ static int cacl_set(struct cli_state *cli, char *filename,
and W2K. JRA.
*/
- sd = make_sec_desc(ctx,old->revision, old->type, old->owner_sid, old->grp_sid,
+ sd = make_sec_desc(ctx,old->revision, old->type, old->owner_sid, old->group_sid,
NULL, old->dacl, &sd_size);
fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS);
diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c
index 0c6a1341c03..ec1e101e061 100644
--- a/source/utils/smbcontrol.c
+++ b/source/utils/smbcontrol.c
@@ -59,7 +59,8 @@ static BOOL send_message(struct process_id pid, int msg_type,
return False;
if (procid_to_pid(&pid) != 0)
- return message_send_pid(pid, msg_type, buf, len, duplicates);
+ return NT_STATUS_IS_OK(message_send_pid(pid, msg_type, buf, len,
+ duplicates));
tdb = tdb_open_log(lock_path("connections.tdb"), 0,
TDB_DEFAULT, O_RDWR, 0);
@@ -98,7 +99,8 @@ static void wait_replies(BOOL multiple_replies)
/* Message handler callback that displays the PID and a string on stdout */
-static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf, size_t len)
+static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf,
+ size_t len, void *private_data)
{
printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
(int)len, (const char *)buf);
@@ -108,7 +110,7 @@ static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf,
/* Message handler callback that displays a string on stdout */
static void print_string_cb(int msg_type, struct process_id pid,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
printf("%.*s", (int)len, (const char *)buf);
num_replies++;
@@ -371,7 +373,8 @@ static BOOL do_election(const struct process_id pid,
/* Ping a samba daemon process */
-static void pong_cb(int msg_type, struct process_id pid, void *buf, size_t len)
+static void pong_cb(int msg_type, struct process_id pid, void *buf,
+ size_t len, void *private_data)
{
char *src_string = procid_str(NULL, &pid);
printf("PONG from pid %s\n", src_string);
@@ -391,7 +394,7 @@ static BOOL do_ping(const struct process_id pid, const int argc, const char **ar
if (!send_message(pid, MSG_PING, NULL, 0, False))
return False;
- message_register(MSG_PONG, pong_cb);
+ message_register(MSG_PONG, pong_cb, NULL);
wait_replies(procid_to_pid(&pid) == 0);
@@ -436,7 +439,8 @@ static BOOL do_profile(const struct process_id pid,
/* Return the profiling level */
-static void profilelevel_cb(int msg_type, struct process_id pid, void *buf, size_t len)
+static void profilelevel_cb(int msg_type, struct process_id pid, void *buf,
+ size_t len, void *private_data)
{
int level;
const char *s;
@@ -473,7 +477,7 @@ static void profilelevel_cb(int msg_type, struct process_id pid, void *buf, size
}
static void profilelevel_rqst(int msg_type, struct process_id pid,
- void *buf, size_t len)
+ void *buf, size_t len, void *private_data)
{
int v = 0;
@@ -495,8 +499,8 @@ static BOOL do_profilelevel(const struct process_id pid,
if (!send_message(pid, MSG_REQ_PROFILELEVEL, NULL, 0, False))
return False;
- message_register(MSG_PROFILELEVEL, profilelevel_cb);
- message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst);
+ message_register(MSG_PROFILELEVEL, profilelevel_cb, NULL);
+ message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst, NULL);
wait_replies(procid_to_pid(&pid) == 0);
@@ -525,7 +529,7 @@ static BOOL do_debuglevel(const struct process_id pid,
if (!send_message(pid, MSG_REQ_DEBUGLEVEL, NULL, 0, False))
return False;
- message_register(MSG_DEBUGLEVEL, print_pid_string_cb);
+ message_register(MSG_DEBUGLEVEL, print_pid_string_cb, NULL);
wait_replies(procid_to_pid(&pid) == 0);
@@ -732,7 +736,7 @@ static BOOL do_poolusage(const struct process_id pid,
return False;
}
- message_register(MSG_POOL_USAGE, print_string_cb);
+ message_register(MSG_POOL_USAGE, print_string_cb, NULL);
/* Send a message and register our interest in a reply */
@@ -882,25 +886,27 @@ static BOOL do_winbind_offline(const struct process_id pid,
5 times. */
for (retry = 0; retry < 5; retry++) {
- int err;
TDB_DATA d;
+ char buf[4];
+
ZERO_STRUCT(d);
+
+ SIVAL(buf, 0, time(NULL));
+ d.dptr = buf;
+ d.dsize = 4;
+
tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False);
/* Check that the entry "WINBINDD_OFFLINE" still exists. */
- tdb->ecode = TDB_SUCCESS;
d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
-
- /* As this is a key with no data we don't need to free, we
- check for existence by looking at tdb_err. */
-
- err = tdb_error(tdb);
-
- if (err == TDB_ERR_NOEXIST) {
+
+ if (!d.dptr || d.dsize != 4) {
+ SAFE_FREE(d.dptr);
DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
} else {
+ SAFE_FREE(d.dptr);
break;
}
}
@@ -921,7 +927,7 @@ static BOOL do_winbind_onlinestatus(const struct process_id pid,
return False;
}
- message_register(MSG_WINBIND_ONLINESTATUS, print_pid_string_cb);
+ message_register(MSG_WINBIND_ONLINESTATUS, print_pid_string_cb, NULL);
if (!send_message(pid, MSG_WINBIND_ONLINESTATUS, &myid, sizeof(myid), False))
return False;
diff --git a/source/utils/smbcquotas.c b/source/utils/smbcquotas.c
index 7b3268e7834..40f4a86f96b 100644
--- a/source/utils/smbcquotas.c
+++ b/source/utils/smbcquotas.c
@@ -79,7 +79,7 @@ static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric)
{
char **domains = NULL;
char **names = NULL;
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
sid_to_string(str, sid);
@@ -106,7 +106,7 @@ static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric)
/* convert a string to a SID, either numeric or username/group */
static BOOL StringToSid(DOM_SID *sid, const char *str)
{
- uint32 *types = NULL;
+ enum lsa_SidType *types = NULL;
DOM_SID *sids = NULL;
BOOL result = True;
diff --git a/source/utils/smbget.c b/source/utils/smbget.c
index 4a2670e0c16..4142b230f27 100644
--- a/source/utils/smbget.c
+++ b/source/utils/smbget.c
@@ -50,9 +50,9 @@ const char *username = NULL, *password = NULL, *workgroup = NULL;
int nonprompt = 0, quiet = 0, dots = 0, keep_permissions = 0, verbose = 0, send_stdout = 0;
int blocksize = SMB_DEFAULT_BLOCKSIZE;
-int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile);
+static int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile);
-int get_num_cols(void)
+static int get_num_cols(void)
{
#ifdef TIOCGWINSZ
struct winsize ws;
@@ -68,12 +68,12 @@ int get_num_cols(void)
#endif
}
-void change_columns(int sig)
+static void change_columns(int sig)
{
columns = get_num_cols();
}
-void human_readable(off_t s, char *buffer, int l)
+static void human_readable(off_t s, char *buffer, int l)
{
if(s > 1024 * 1024 * 1024) snprintf(buffer, l, "%.2fGb", 1.0 * s / (1024 * 1024 * 1024));
else if(s > 1024 * 1024) snprintf(buffer, l, "%.2fMb", 1.0 * s / (1024 * 1024));
@@ -81,7 +81,7 @@ void human_readable(off_t s, char *buffer, int l)
else snprintf(buffer, l, OFF_T_FORMAT"b", (OFF_T_FORMAT_CAST)s);
}
-void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
+static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
{
static char hasasked = 0;
char *wgtmp, *usertmp;
@@ -113,7 +113,7 @@ void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *
free(wgtmp); free(usertmp);
}
-int smb_download_dir(const char *base, const char *name, int resume)
+static int smb_download_dir(const char *base, const char *name, int resume)
{
char path[SMB_MAXPATHLEN];
int dirhandle;
@@ -199,7 +199,7 @@ int smb_download_dir(const char *base, const char *name, int resume)
return 1;
}
-char *print_time(long t)
+static char *print_time(long t)
{
static char buffer[100];
int secs, mins, hours;
@@ -215,7 +215,7 @@ char *print_time(long t)
return buffer;
}
-void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total)
+static void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total)
{
double avg = 0.0;
long eta = -1;
@@ -244,7 +244,7 @@ void print_progress(const char *name, time_t start, time_t now, off_t start_pos,
free(filename); free(status);
}
-int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile) {
+static int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile) {
int remotehandle, localhandle;
time_t start_time = time(NULL);
const char *newpath;
@@ -388,7 +388,7 @@ int smb_download_file(const char *base, const char *name, int recursive, int res
offset_check = 0;
}
- readbuf = SMB_MALLOC(blocksize);
+ readbuf = (char *)SMB_MALLOC(blocksize);
/* Now, download all bytes from offset_download to the end */
for(curpos = offset_download; curpos < remotestat.st_size; curpos+=blocksize) {
@@ -447,7 +447,7 @@ int smb_download_file(const char *base, const char *name, int recursive, int res
return 1;
}
-void clean_exit(void)
+static void clean_exit(void)
{
char bs[100];
human_readable(total_bytes, bs, sizeof(bs));
@@ -455,12 +455,12 @@ void clean_exit(void)
exit(0);
}
-void signal_quit(int v)
+static void signal_quit(int v)
{
clean_exit();
}
-int readrcfile(const char *name, const struct poptOption long_options[])
+static int readrcfile(const char *name, const struct poptOption long_options[])
{
FILE *fd = fopen(name, "r");
int lineno = 0, i;
diff --git a/source/utils/status.c b/source/utils/status.c
index 163d99a2f69..4f66501511b 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -48,6 +48,9 @@ static BOOL numeric_only = False;
const char *username = NULL;
+extern BOOL status_profile_dump(BOOL be_verbose);
+extern BOOL status_profile_rates(BOOL be_verbose);
+
/* added by OH */
static void Ucrit_addUid(uid_t uid)
{
@@ -98,7 +101,10 @@ static BOOL Ucrit_addPid( pid_t pid )
return True;
}
-static void print_share_mode(const struct share_mode_entry *e, const char *sharepath, const char *fname)
+static void print_share_mode(const struct share_mode_entry *e,
+ const char *sharepath,
+ const char *fname,
+ void *dummy)
{
static int count;
@@ -182,368 +188,6 @@ static void print_brl(SMB_DEV_T dev,
(double)start, (double)size);
}
-
-/*******************************************************************
- dump the elements of the profile structure
- ******************************************************************/
-static int profile_dump(void)
-{
-#ifdef WITH_PROFILE
- if (!profile_setup(True)) {
- fprintf(stderr,"Failed to initialise profile memory\n");
- return -1;
- }
-
- d_printf("smb_count: %u\n", profile_p->smb_count);
- d_printf("uid_changes: %u\n", profile_p->uid_changes);
- d_printf("************************ System Calls ****************************\n");
- d_printf("opendir_count: %u\n", profile_p->syscall_opendir_count);
- d_printf("opendir_time: %u\n", profile_p->syscall_opendir_time);
- d_printf("readdir_count: %u\n", profile_p->syscall_readdir_count);
- d_printf("readdir_time: %u\n", profile_p->syscall_readdir_time);
- d_printf("mkdir_count: %u\n", profile_p->syscall_mkdir_count);
- d_printf("mkdir_time: %u\n", profile_p->syscall_mkdir_time);
- d_printf("rmdir_count: %u\n", profile_p->syscall_rmdir_count);
- d_printf("rmdir_time: %u\n", profile_p->syscall_rmdir_time);
- d_printf("closedir_count: %u\n", profile_p->syscall_closedir_count);
- d_printf("closedir_time: %u\n", profile_p->syscall_closedir_time);
- d_printf("open_count: %u\n", profile_p->syscall_open_count);
- d_printf("open_time: %u\n", profile_p->syscall_open_time);
- d_printf("close_count: %u\n", profile_p->syscall_close_count);
- d_printf("close_time: %u\n", profile_p->syscall_close_time);
- d_printf("read_count: %u\n", profile_p->syscall_read_count);
- d_printf("read_time: %u\n", profile_p->syscall_read_time);
- d_printf("read_bytes: %u\n", profile_p->syscall_read_bytes);
- d_printf("write_count: %u\n", profile_p->syscall_write_count);
- d_printf("write_time: %u\n", profile_p->syscall_write_time);
- d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes);
- d_printf("pread_count: %u\n", profile_p->syscall_pread_count);
- d_printf("pread_time: %u\n", profile_p->syscall_pread_time);
- d_printf("pread_bytes: %u\n", profile_p->syscall_pread_bytes);
- d_printf("pwrite_count: %u\n", profile_p->syscall_pwrite_count);
- d_printf("pwrite_time: %u\n", profile_p->syscall_pwrite_time);
- d_printf("pwrite_bytes: %u\n", profile_p->syscall_pwrite_bytes);
-#ifdef WITH_SENDFILE
- d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count);
- d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time);
- d_printf("sendfile_bytes: %u\n", profile_p->syscall_sendfile_bytes);
-#endif
- d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count);
- d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time);
- d_printf("rename_count: %u\n", profile_p->syscall_rename_count);
- d_printf("rename_time: %u\n", profile_p->syscall_rename_time);
- d_printf("fsync_count: %u\n", profile_p->syscall_fsync_count);
- d_printf("fsync_time: %u\n", profile_p->syscall_fsync_time);
- d_printf("stat_count: %u\n", profile_p->syscall_stat_count);
- d_printf("stat_time: %u\n", profile_p->syscall_stat_time);
- d_printf("fstat_count: %u\n", profile_p->syscall_fstat_count);
- d_printf("fstat_time: %u\n", profile_p->syscall_fstat_time);
- d_printf("lstat_count: %u\n", profile_p->syscall_lstat_count);
- d_printf("lstat_time: %u\n", profile_p->syscall_lstat_time);
- d_printf("unlink_count: %u\n", profile_p->syscall_unlink_count);
- d_printf("unlink_time: %u\n", profile_p->syscall_unlink_time);
- d_printf("chmod_count: %u\n", profile_p->syscall_chmod_count);
- d_printf("chmod_time: %u\n", profile_p->syscall_chmod_time);
- d_printf("fchmod_count: %u\n", profile_p->syscall_fchmod_count);
- d_printf("fchmod_time: %u\n", profile_p->syscall_fchmod_time);
- d_printf("chown_count: %u\n", profile_p->syscall_chown_count);
- d_printf("chown_time: %u\n", profile_p->syscall_chown_time);
- d_printf("fchown_count: %u\n", profile_p->syscall_fchown_count);
- d_printf("fchown_time: %u\n", profile_p->syscall_fchown_time);
- d_printf("chdir_count: %u\n", profile_p->syscall_chdir_count);
- d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time);
- d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count);
- d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time);
- d_printf("utime_count: %u\n", profile_p->syscall_utime_count);
- d_printf("utime_time: %u\n", profile_p->syscall_utime_time);
- d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count);
- d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time);
- d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count);
- d_printf("fcntl_lock_time: %u\n", profile_p->syscall_fcntl_lock_time);
- d_printf("readlink_count: %u\n", profile_p->syscall_readlink_count);
- d_printf("readlink_time: %u\n", profile_p->syscall_readlink_time);
- d_printf("symlink_count: %u\n", profile_p->syscall_symlink_count);
- d_printf("symlink_time: %u\n", profile_p->syscall_symlink_time);
- d_printf("************************ Statcache *******************************\n");
- d_printf("lookups: %u\n", profile_p->statcache_lookups);
- d_printf("misses: %u\n", profile_p->statcache_misses);
- d_printf("hits: %u\n", profile_p->statcache_hits);
- d_printf("************************ Writecache ******************************\n");
- d_printf("read_hits: %u\n", profile_p->writecache_read_hits);
- d_printf("abutted_writes: %u\n", profile_p->writecache_abutted_writes);
- d_printf("total_writes: %u\n", profile_p->writecache_total_writes);
- d_printf("non_oplock_writes: %u\n", profile_p->writecache_non_oplock_writes);
- d_printf("direct_writes: %u\n", profile_p->writecache_direct_writes);
- d_printf("init_writes: %u\n", profile_p->writecache_init_writes);
- d_printf("flushed_writes[SEEK]: %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]);
- d_printf("flushed_writes[READ]: %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]);
- d_printf("flushed_writes[WRITE]: %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]);
- d_printf("flushed_writes[READRAW]: %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]);
- d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]);
- d_printf("flushed_writes[CLOSE]: %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]);
- d_printf("flushed_writes[SYNC]: %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]);
- d_printf("flushed_writes[SIZECHANGE]: %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]);
- d_printf("num_perfect_writes: %u\n", profile_p->writecache_num_perfect_writes);
- d_printf("num_write_caches: %u\n", profile_p->writecache_num_write_caches);
- d_printf("allocated_write_caches: %u\n", profile_p->writecache_allocated_write_caches);
- d_printf("************************ SMB Calls *******************************\n");
- d_printf("mkdir_count: %u\n", profile_p->SMBmkdir_count);
- d_printf("mkdir_time: %u\n", profile_p->SMBmkdir_time);
- d_printf("rmdir_count: %u\n", profile_p->SMBrmdir_count);
- d_printf("rmdir_time: %u\n", profile_p->SMBrmdir_time);
- d_printf("open_count: %u\n", profile_p->SMBopen_count);
- d_printf("open_time: %u\n", profile_p->SMBopen_time);
- d_printf("create_count: %u\n", profile_p->SMBcreate_count);
- d_printf("create_time: %u\n", profile_p->SMBcreate_time);
- d_printf("close_count: %u\n", profile_p->SMBclose_count);
- d_printf("close_time: %u\n", profile_p->SMBclose_time);
- d_printf("flush_count: %u\n", profile_p->SMBflush_count);
- d_printf("flush_time: %u\n", profile_p->SMBflush_time);
- d_printf("unlink_count: %u\n", profile_p->SMBunlink_count);
- d_printf("unlink_time: %u\n", profile_p->SMBunlink_time);
- d_printf("mv_count: %u\n", profile_p->SMBmv_count);
- d_printf("mv_time: %u\n", profile_p->SMBmv_time);
- d_printf("getatr_count: %u\n", profile_p->SMBgetatr_count);
- d_printf("getatr_time: %u\n", profile_p->SMBgetatr_time);
- d_printf("setatr_count: %u\n", profile_p->SMBsetatr_count);
- d_printf("setatr_time: %u\n", profile_p->SMBsetatr_time);
- d_printf("read_count: %u\n", profile_p->SMBread_count);
- d_printf("read_time: %u\n", profile_p->SMBread_time);
- d_printf("write_count: %u\n", profile_p->SMBwrite_count);
- d_printf("write_time: %u\n", profile_p->SMBwrite_time);
- d_printf("lock_count: %u\n", profile_p->SMBlock_count);
- d_printf("lock_time: %u\n", profile_p->SMBlock_time);
- d_printf("unlock_count: %u\n", profile_p->SMBunlock_count);
- d_printf("unlock_time: %u\n", profile_p->SMBunlock_time);
- d_printf("ctemp_count: %u\n", profile_p->SMBctemp_count);
- d_printf("ctemp_time: %u\n", profile_p->SMBctemp_time);
- d_printf("mknew_count: %u\n", profile_p->SMBmknew_count);
- d_printf("mknew_time: %u\n", profile_p->SMBmknew_time);
- d_printf("chkpth_count: %u\n", profile_p->SMBchkpth_count);
- d_printf("chkpth_time: %u\n", profile_p->SMBchkpth_time);
- d_printf("exit_count: %u\n", profile_p->SMBexit_count);
- d_printf("exit_time: %u\n", profile_p->SMBexit_time);
- d_printf("lseek_count: %u\n", profile_p->SMBlseek_count);
- d_printf("lseek_time: %u\n", profile_p->SMBlseek_time);
- d_printf("lockread_count: %u\n", profile_p->SMBlockread_count);
- d_printf("lockread_time: %u\n", profile_p->SMBlockread_time);
- d_printf("writeunlock_count: %u\n", profile_p->SMBwriteunlock_count);
- d_printf("writeunlock_time: %u\n", profile_p->SMBwriteunlock_time);
- d_printf("readbraw_count: %u\n", profile_p->SMBreadbraw_count);
- d_printf("readbraw_time: %u\n", profile_p->SMBreadbraw_time);
- d_printf("readBmpx_count: %u\n", profile_p->SMBreadBmpx_count);
- d_printf("readBmpx_time: %u\n", profile_p->SMBreadBmpx_time);
- d_printf("readBs_count: %u\n", profile_p->SMBreadBs_count);
- d_printf("readBs_time: %u\n", profile_p->SMBreadBs_time);
- d_printf("writebraw_count: %u\n", profile_p->SMBwritebraw_count);
- d_printf("writebraw_time: %u\n", profile_p->SMBwritebraw_time);
- d_printf("writeBmpx_count: %u\n", profile_p->SMBwriteBmpx_count);
- d_printf("writeBmpx_time: %u\n", profile_p->SMBwriteBmpx_time);
- d_printf("writeBs_count: %u\n", profile_p->SMBwriteBs_count);
- d_printf("writeBs_time: %u\n", profile_p->SMBwriteBs_time);
- d_printf("writec_count: %u\n", profile_p->SMBwritec_count);
- d_printf("writec_time: %u\n", profile_p->SMBwritec_time);
- d_printf("setattrE_count: %u\n", profile_p->SMBsetattrE_count);
- d_printf("setattrE_time: %u\n", profile_p->SMBsetattrE_time);
- d_printf("getattrE_count: %u\n", profile_p->SMBgetattrE_count);
- d_printf("getattrE_time: %u\n", profile_p->SMBgetattrE_time);
- d_printf("lockingX_count: %u\n", profile_p->SMBlockingX_count);
- d_printf("lockingX_time: %u\n", profile_p->SMBlockingX_time);
- d_printf("trans_count: %u\n", profile_p->SMBtrans_count);
- d_printf("trans_time: %u\n", profile_p->SMBtrans_time);
- d_printf("transs_count: %u\n", profile_p->SMBtranss_count);
- d_printf("transs_time: %u\n", profile_p->SMBtranss_time);
- d_printf("ioctl_count: %u\n", profile_p->SMBioctl_count);
- d_printf("ioctl_time: %u\n", profile_p->SMBioctl_time);
- d_printf("ioctls_count: %u\n", profile_p->SMBioctls_count);
- d_printf("ioctls_time: %u\n", profile_p->SMBioctls_time);
- d_printf("copy_count: %u\n", profile_p->SMBcopy_count);
- d_printf("copy_time: %u\n", profile_p->SMBcopy_time);
- d_printf("move_count: %u\n", profile_p->SMBmove_count);
- d_printf("move_time: %u\n", profile_p->SMBmove_time);
- d_printf("echo_count: %u\n", profile_p->SMBecho_count);
- d_printf("echo_time: %u\n", profile_p->SMBecho_time);
- d_printf("writeclose_count: %u\n", profile_p->SMBwriteclose_count);
- d_printf("writeclose_time: %u\n", profile_p->SMBwriteclose_time);
- d_printf("openX_count: %u\n", profile_p->SMBopenX_count);
- d_printf("openX_time: %u\n", profile_p->SMBopenX_time);
- d_printf("readX_count: %u\n", profile_p->SMBreadX_count);
- d_printf("readX_time: %u\n", profile_p->SMBreadX_time);
- d_printf("writeX_count: %u\n", profile_p->SMBwriteX_count);
- d_printf("writeX_time: %u\n", profile_p->SMBwriteX_time);
- d_printf("trans2_count: %u\n", profile_p->SMBtrans2_count);
- d_printf("trans2_time: %u\n", profile_p->SMBtrans2_time);
- d_printf("transs2_count: %u\n", profile_p->SMBtranss2_count);
- d_printf("transs2_time: %u\n", profile_p->SMBtranss2_time);
- d_printf("findclose_count: %u\n", profile_p->SMBfindclose_count);
- d_printf("findclose_time: %u\n", profile_p->SMBfindclose_time);
- d_printf("findnclose_count: %u\n", profile_p->SMBfindnclose_count);
- d_printf("findnclose_time: %u\n", profile_p->SMBfindnclose_time);
- d_printf("tcon_count: %u\n", profile_p->SMBtcon_count);
- d_printf("tcon_time: %u\n", profile_p->SMBtcon_time);
- d_printf("tdis_count: %u\n", profile_p->SMBtdis_count);
- d_printf("tdis_time: %u\n", profile_p->SMBtdis_time);
- d_printf("negprot_count: %u\n", profile_p->SMBnegprot_count);
- d_printf("negprot_time: %u\n", profile_p->SMBnegprot_time);
- d_printf("sesssetupX_count: %u\n", profile_p->SMBsesssetupX_count);
- d_printf("sesssetupX_time: %u\n", profile_p->SMBsesssetupX_time);
- d_printf("ulogoffX_count: %u\n", profile_p->SMBulogoffX_count);
- d_printf("ulogoffX_time: %u\n", profile_p->SMBulogoffX_time);
- d_printf("tconX_count: %u\n", profile_p->SMBtconX_count);
- d_printf("tconX_time: %u\n", profile_p->SMBtconX_time);
- d_printf("dskattr_count: %u\n", profile_p->SMBdskattr_count);
- d_printf("dskattr_time: %u\n", profile_p->SMBdskattr_time);
- d_printf("search_count: %u\n", profile_p->SMBsearch_count);
- d_printf("search_time: %u\n", profile_p->SMBsearch_time);
- d_printf("ffirst_count: %u\n", profile_p->SMBffirst_count);
- d_printf("ffirst_time: %u\n", profile_p->SMBffirst_time);
- d_printf("funique_count: %u\n", profile_p->SMBfunique_count);
- d_printf("funique_time: %u\n", profile_p->SMBfunique_time);
- d_printf("fclose_count: %u\n", profile_p->SMBfclose_count);
- d_printf("fclose_time: %u\n", profile_p->SMBfclose_time);
- d_printf("nttrans_count: %u\n", profile_p->SMBnttrans_count);
- d_printf("nttrans_time: %u\n", profile_p->SMBnttrans_time);
- d_printf("nttranss_count: %u\n", profile_p->SMBnttranss_count);
- d_printf("nttranss_time: %u\n", profile_p->SMBnttranss_time);
- d_printf("ntcreateX_count: %u\n", profile_p->SMBntcreateX_count);
- d_printf("ntcreateX_time: %u\n", profile_p->SMBntcreateX_time);
- d_printf("ntcancel_count: %u\n", profile_p->SMBntcancel_count);
- d_printf("ntcancel_time: %u\n", profile_p->SMBntcancel_time);
- d_printf("splopen_count: %u\n", profile_p->SMBsplopen_count);
- d_printf("splopen_time: %u\n", profile_p->SMBsplopen_time);
- d_printf("splwr_count: %u\n", profile_p->SMBsplwr_count);
- d_printf("splwr_time: %u\n", profile_p->SMBsplwr_time);
- d_printf("splclose_count: %u\n", profile_p->SMBsplclose_count);
- d_printf("splclose_time: %u\n", profile_p->SMBsplclose_time);
- d_printf("splretq_count: %u\n", profile_p->SMBsplretq_count);
- d_printf("splretq_time: %u\n", profile_p->SMBsplretq_time);
- d_printf("sends_count: %u\n", profile_p->SMBsends_count);
- d_printf("sends_time: %u\n", profile_p->SMBsends_time);
- d_printf("sendb_count: %u\n", profile_p->SMBsendb_count);
- d_printf("sendb_time: %u\n", profile_p->SMBsendb_time);
- d_printf("fwdname_count: %u\n", profile_p->SMBfwdname_count);
- d_printf("fwdname_time: %u\n", profile_p->SMBfwdname_time);
- d_printf("cancelf_count: %u\n", profile_p->SMBcancelf_count);
- d_printf("cancelf_time: %u\n", profile_p->SMBcancelf_time);
- d_printf("getmac_count: %u\n", profile_p->SMBgetmac_count);
- d_printf("getmac_time: %u\n", profile_p->SMBgetmac_time);
- d_printf("sendstrt_count: %u\n", profile_p->SMBsendstrt_count);
- d_printf("sendstrt_time: %u\n", profile_p->SMBsendstrt_time);
- d_printf("sendend_count: %u\n", profile_p->SMBsendend_count);
- d_printf("sendend_time: %u\n", profile_p->SMBsendend_time);
- d_printf("sendtxt_count: %u\n", profile_p->SMBsendtxt_count);
- d_printf("sendtxt_time: %u\n", profile_p->SMBsendtxt_time);
- d_printf("invalid_count: %u\n", profile_p->SMBinvalid_count);
- d_printf("invalid_time: %u\n", profile_p->SMBinvalid_time);
- d_printf("************************ Pathworks Calls *************************\n");
- d_printf("setdir_count: %u\n", profile_p->pathworks_setdir_count);
- d_printf("setdir_time: %u\n", profile_p->pathworks_setdir_time);
- d_printf("************************ Trans2 Calls ****************************\n");
- d_printf("open_count: %u\n", profile_p->Trans2_open_count);
- d_printf("open_time: %u\n", profile_p->Trans2_open_time);
- d_printf("findfirst_count: %u\n", profile_p->Trans2_findfirst_count);
- d_printf("findfirst_time: %u\n", profile_p->Trans2_findfirst_time);
- d_printf("findnext_count: %u\n", profile_p->Trans2_findnext_count);
- d_printf("findnext_time: %u\n", profile_p->Trans2_findnext_time);
- d_printf("qfsinfo_count: %u\n", profile_p->Trans2_qfsinfo_count);
- d_printf("qfsinfo_time: %u\n", profile_p->Trans2_qfsinfo_time);
- d_printf("setfsinfo_count: %u\n", profile_p->Trans2_setfsinfo_count);
- d_printf("setfsinfo_time: %u\n", profile_p->Trans2_setfsinfo_time);
- d_printf("qpathinfo_count: %u\n", profile_p->Trans2_qpathinfo_count);
- d_printf("qpathinfo_time: %u\n", profile_p->Trans2_qpathinfo_time);
- d_printf("setpathinfo_count: %u\n", profile_p->Trans2_setpathinfo_count);
- d_printf("setpathinfo_time: %u\n", profile_p->Trans2_setpathinfo_time);
- d_printf("qfileinfo_count: %u\n", profile_p->Trans2_qfileinfo_count);
- d_printf("qfileinfo_time: %u\n", profile_p->Trans2_qfileinfo_time);
- d_printf("setfileinfo_count: %u\n", profile_p->Trans2_setfileinfo_count);
- d_printf("setfileinfo_time: %u\n", profile_p->Trans2_setfileinfo_time);
- d_printf("fsctl_count: %u\n", profile_p->Trans2_fsctl_count);
- d_printf("fsctl_time: %u\n", profile_p->Trans2_fsctl_time);
- d_printf("ioctl_count: %u\n", profile_p->Trans2_ioctl_count);
- d_printf("ioctl_time: %u\n", profile_p->Trans2_ioctl_time);
- d_printf("findnotifyfirst_count: %u\n", profile_p->Trans2_findnotifyfirst_count);
- d_printf("findnotifyfirst_time: %u\n", profile_p->Trans2_findnotifyfirst_time);
- d_printf("findnotifynext_count: %u\n", profile_p->Trans2_findnotifynext_count);
- d_printf("findnotifynext_time: %u\n", profile_p->Trans2_findnotifynext_time);
- d_printf("mkdir_count: %u\n", profile_p->Trans2_mkdir_count);
- d_printf("mkdir_time: %u\n", profile_p->Trans2_mkdir_time);
- d_printf("session_setup_count: %u\n", profile_p->Trans2_session_setup_count);
- d_printf("session_setup_time: %u\n", profile_p->Trans2_session_setup_time);
- d_printf("get_dfs_referral_count: %u\n", profile_p->Trans2_get_dfs_referral_count);
- d_printf("get_dfs_referral_time: %u\n", profile_p->Trans2_get_dfs_referral_time);
- d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count);
- d_printf("report_dfs_inconsistancy_time: %u\n", profile_p->Trans2_report_dfs_inconsistancy_time);
- d_printf("************************ NT Transact Calls ***********************\n");
- d_printf("create_count: %u\n", profile_p->NT_transact_create_count);
- d_printf("create_time: %u\n", profile_p->NT_transact_create_time);
- d_printf("ioctl_count: %u\n", profile_p->NT_transact_ioctl_count);
- d_printf("ioctl_time: %u\n", profile_p->NT_transact_ioctl_time);
- d_printf("set_security_desc_count: %u\n", profile_p->NT_transact_set_security_desc_count);
- d_printf("set_security_desc_time: %u\n", profile_p->NT_transact_set_security_desc_time);
- d_printf("notify_change_count: %u\n", profile_p->NT_transact_notify_change_count);
- d_printf("notify_change_time: %u\n", profile_p->NT_transact_notify_change_time);
- d_printf("rename_count: %u\n", profile_p->NT_transact_rename_count);
- d_printf("rename_time: %u\n", profile_p->NT_transact_rename_time);
- d_printf("query_security_desc_count: %u\n", profile_p->NT_transact_query_security_desc_count);
- d_printf("query_security_desc_time: %u\n", profile_p->NT_transact_query_security_desc_time);
- d_printf("************************ ACL Calls *******************************\n");
- d_printf("get_nt_acl_count: %u\n", profile_p->get_nt_acl_count);
- d_printf("get_nt_acl_time: %u\n", profile_p->get_nt_acl_time);
- d_printf("fget_nt_acl_count: %u\n", profile_p->fget_nt_acl_count);
- d_printf("fget_nt_acl_time: %u\n", profile_p->fget_nt_acl_time);
- d_printf("set_nt_acl_count: %u\n", profile_p->set_nt_acl_count);
- d_printf("set_nt_acl_time: %u\n", profile_p->set_nt_acl_time);
- d_printf("fset_nt_acl_count: %u\n", profile_p->fset_nt_acl_count);
- d_printf("fset_nt_acl_time: %u\n", profile_p->fset_nt_acl_time);
- d_printf("chmod_acl_count: %u\n", profile_p->chmod_acl_count);
- d_printf("chmod_acl_time: %u\n", profile_p->chmod_acl_time);
- d_printf("fchmod_acl_count: %u\n", profile_p->fchmod_acl_count);
- d_printf("fchmod_acl_time: %u\n", profile_p->fchmod_acl_time);
- d_printf("************************ NMBD Calls ****************************\n");
- d_printf("name_release_count: %u\n", profile_p->name_release_count);
- d_printf("name_release_time: %u\n", profile_p->name_release_time);
- d_printf("name_refresh_count: %u\n", profile_p->name_refresh_count);
- d_printf("name_refresh_time: %u\n", profile_p->name_refresh_time);
- d_printf("name_registration_count: %u\n", profile_p->name_registration_count);
- d_printf("name_registration_time: %u\n", profile_p->name_registration_time);
- d_printf("node_status_count: %u\n", profile_p->node_status_count);
- d_printf("node_status_time: %u\n", profile_p->node_status_time);
- d_printf("name_query_count: %u\n", profile_p->name_query_count);
- d_printf("name_query_time: %u\n", profile_p->name_query_time);
- d_printf("host_announce_count: %u\n", profile_p->host_announce_count);
- d_printf("host_announce_time: %u\n", profile_p->host_announce_time);
- d_printf("workgroup_announce_count: %u\n", profile_p->workgroup_announce_count);
- d_printf("workgroup_announce_time: %u\n", profile_p->workgroup_announce_time);
- d_printf("local_master_announce_count: %u\n", profile_p->local_master_announce_count);
- d_printf("local_master_announce_time: %u\n", profile_p->local_master_announce_time);
- d_printf("master_browser_announce_count: %u\n", profile_p->master_browser_announce_count);
- d_printf("master_browser_announce_time: %u\n", profile_p->master_browser_announce_time);
- d_printf("lm_host_announce_count: %u\n", profile_p->lm_host_announce_count);
- d_printf("lm_host_announce_time: %u\n", profile_p->lm_host_announce_time);
- d_printf("get_backup_list_count: %u\n", profile_p->get_backup_list_count);
- d_printf("get_backup_list_time: %u\n", profile_p->get_backup_list_time);
- d_printf("reset_browser_count: %u\n", profile_p->reset_browser_count);
- d_printf("reset_browser_time: %u\n", profile_p->reset_browser_time);
- d_printf("announce_request_count: %u\n", profile_p->announce_request_count);
- d_printf("announce_request_time: %u\n", profile_p->announce_request_time);
- d_printf("lm_announce_request_count: %u\n", profile_p->lm_announce_request_count);
- d_printf("lm_announce_request_time: %u\n", profile_p->lm_announce_request_time);
- d_printf("domain_logon_count: %u\n", profile_p->domain_logon_count);
- d_printf("domain_logon_time: %u\n", profile_p->domain_logon_time);
- d_printf("sync_browse_lists_count: %u\n", profile_p->sync_browse_lists_count);
- d_printf("sync_browse_lists_time: %u\n", profile_p->sync_browse_lists_time);
- d_printf("run_elections_count: %u\n", profile_p->run_elections_count);
- d_printf("run_elections_time: %u\n", profile_p->run_elections_time);
- d_printf("election_count: %u\n", profile_p->election_count);
- d_printf("election_time: %u\n", profile_p->election_time);
-#else /* WITH_PROFILE */
- fprintf(stderr, "Profile data unavailable\n");
-#endif /* WITH_PROFILE */
-
- return 0;
-}
-
-
static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
struct connections_data crec;
@@ -602,7 +246,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
int main(int argc, char *argv[])
{
int c;
- static int profile_only = 0;
+ int profile_only = 0;
TDB_CONTEXT *tdb;
BOOL show_processes, show_locks, show_shares;
poptContext pc;
@@ -614,9 +258,8 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
{"shares", 'S', POPT_ARG_NONE, &shares_only, 'S', "Show shares only" },
{"user", 'u', POPT_ARG_STRING, &username, 'u', "Switch to user" },
{"brief", 'b', POPT_ARG_NONE, &brief, 'b', "Be brief" },
-#ifdef WITH_PROFILE
- {"profile", 'P', POPT_ARG_NONE, &profile_only, 'P', "Do profiling" },
-#endif /* WITH_PROFILE */
+ {"profile", 'P', POPT_ARG_NONE, NULL, 'P', "Do profiling" },
+ {"profile-rates", 'R', POPT_ARG_NONE, NULL, 'R', "Show call rates" },
{"byterange", 'B', POPT_ARG_NONE, &show_brl, 'B', "Include byte range locks"},
{"numeric", 'n', POPT_ARG_NONE, &numeric_only, 'n', "Numeric uid/gid"},
POPT_COMMON_SAMBA
@@ -643,6 +286,9 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
case 'u':
Ucrit_addUid(nametouid(poptGetOptArg(pc)));
break;
+ case 'P':
+ case 'R':
+ profile_only = c;
}
}
@@ -663,11 +309,18 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
return (-1);
}
-
- if (profile_only) {
- return profile_dump();
+
+ switch (profile_only) {
+ case 'P':
+ /* Dump profile data */
+ return status_profile_dump(verbose);
+ case 'R':
+ /* Continuously display rate-converted data */
+ return status_profile_rates(verbose);
+ default:
+ break;
}
-
+
if ( show_processes ) {
tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
if (!tdb) {
@@ -719,7 +372,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
exit(1);
}
- ret = share_mode_forall(print_share_mode);
+ ret = share_mode_forall(print_share_mode, NULL);
if (ret == 0) {
d_printf("No locked files\n");
diff --git a/source/utils/status_profile.c b/source/utils/status_profile.c
new file mode 100644
index 00000000000..9224fc176cb
--- /dev/null
+++ b/source/utils/status_profile.c
@@ -0,0 +1,544 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * status reporting
+ * Copyright (C) Andrew Tridgell 1994-1998
+ * Copyright (C) James Peach 2005-2006
+ *
+ * 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"
+
+BOOL status_profile_dump(BOOL be_verbose);
+BOOL status_profile_rates(BOOL be_verbose);
+
+#ifdef WITH_PROFILE
+static void profile_separator(const char * title)
+{
+ char line[79 + 1];
+ char * end;
+
+ snprintf(line, sizeof(line), "**** %s ", title);
+
+ for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
+ *end = '*';
+ }
+
+ line[sizeof(line) - 1] = '\0';
+ d_printf("%s\n", line);
+}
+#endif
+
+/*******************************************************************
+ dump the elements of the profile structure
+ ******************************************************************/
+BOOL status_profile_dump(BOOL verbose)
+{
+#ifdef WITH_PROFILE
+ if (!profile_setup(True)) {
+ fprintf(stderr,"Failed to initialise profile memory\n");
+ return False;
+ }
+
+ d_printf("smb_count: %u\n", profile_p->smb_count);
+ d_printf("uid_changes: %u\n", profile_p->uid_changes);
+
+ profile_separator("System Calls");
+ d_printf("opendir_count: %u\n", profile_p->syscall_opendir_count);
+ d_printf("opendir_time: %u\n", profile_p->syscall_opendir_time);
+ d_printf("readdir_count: %u\n", profile_p->syscall_readdir_count);
+ d_printf("readdir_time: %u\n", profile_p->syscall_readdir_time);
+ d_printf("mkdir_count: %u\n", profile_p->syscall_mkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->syscall_mkdir_time);
+ d_printf("rmdir_count: %u\n", profile_p->syscall_rmdir_count);
+ d_printf("rmdir_time: %u\n", profile_p->syscall_rmdir_time);
+ d_printf("closedir_count: %u\n", profile_p->syscall_closedir_count);
+ d_printf("closedir_time: %u\n", profile_p->syscall_closedir_time);
+ d_printf("open_count: %u\n", profile_p->syscall_open_count);
+ d_printf("open_time: %u\n", profile_p->syscall_open_time);
+ d_printf("close_count: %u\n", profile_p->syscall_close_count);
+ d_printf("close_time: %u\n", profile_p->syscall_close_time);
+ d_printf("read_count: %u\n", profile_p->syscall_read_count);
+ d_printf("read_time: %u\n", profile_p->syscall_read_time);
+ d_printf("read_bytes: %u\n", profile_p->syscall_read_bytes);
+ d_printf("write_count: %u\n", profile_p->syscall_write_count);
+ d_printf("write_time: %u\n", profile_p->syscall_write_time);
+ d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes);
+ d_printf("pread_count: %u\n", profile_p->syscall_pread_count);
+ d_printf("pread_time: %u\n", profile_p->syscall_pread_time);
+ d_printf("pread_bytes: %u\n", profile_p->syscall_pread_bytes);
+ d_printf("pwrite_count: %u\n", profile_p->syscall_pwrite_count);
+ d_printf("pwrite_time: %u\n", profile_p->syscall_pwrite_time);
+ d_printf("pwrite_bytes: %u\n", profile_p->syscall_pwrite_bytes);
+#ifdef WITH_SENDFILE
+ d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count);
+ d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time);
+ d_printf("sendfile_bytes: %u\n", profile_p->syscall_sendfile_bytes);
+#endif
+ d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count);
+ d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time);
+ d_printf("rename_count: %u\n", profile_p->syscall_rename_count);
+ d_printf("rename_time: %u\n", profile_p->syscall_rename_time);
+ d_printf("fsync_count: %u\n", profile_p->syscall_fsync_count);
+ d_printf("fsync_time: %u\n", profile_p->syscall_fsync_time);
+ d_printf("stat_count: %u\n", profile_p->syscall_stat_count);
+ d_printf("stat_time: %u\n", profile_p->syscall_stat_time);
+ d_printf("fstat_count: %u\n", profile_p->syscall_fstat_count);
+ d_printf("fstat_time: %u\n", profile_p->syscall_fstat_time);
+ d_printf("lstat_count: %u\n", profile_p->syscall_lstat_count);
+ d_printf("lstat_time: %u\n", profile_p->syscall_lstat_time);
+ d_printf("unlink_count: %u\n", profile_p->syscall_unlink_count);
+ d_printf("unlink_time: %u\n", profile_p->syscall_unlink_time);
+ d_printf("chmod_count: %u\n", profile_p->syscall_chmod_count);
+ d_printf("chmod_time: %u\n", profile_p->syscall_chmod_time);
+ d_printf("fchmod_count: %u\n", profile_p->syscall_fchmod_count);
+ d_printf("fchmod_time: %u\n", profile_p->syscall_fchmod_time);
+ d_printf("chown_count: %u\n", profile_p->syscall_chown_count);
+ d_printf("chown_time: %u\n", profile_p->syscall_chown_time);
+ d_printf("fchown_count: %u\n", profile_p->syscall_fchown_count);
+ d_printf("fchown_time: %u\n", profile_p->syscall_fchown_time);
+ d_printf("chdir_count: %u\n", profile_p->syscall_chdir_count);
+ d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time);
+ d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count);
+ d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time);
+ d_printf("utime_count: %u\n", profile_p->syscall_utime_count);
+ d_printf("utime_time: %u\n", profile_p->syscall_utime_time);
+ d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count);
+ d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time);
+ d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count);
+ d_printf("fcntl_lock_time: %u\n", profile_p->syscall_fcntl_lock_time);
+ d_printf("readlink_count: %u\n", profile_p->syscall_readlink_count);
+ d_printf("readlink_time: %u\n", profile_p->syscall_readlink_time);
+ d_printf("symlink_count: %u\n", profile_p->syscall_symlink_count);
+ d_printf("symlink_time: %u\n", profile_p->syscall_symlink_time);
+
+ profile_separator("Stat Cache");
+ d_printf("lookups: %u\n", profile_p->statcache_lookups);
+ d_printf("misses: %u\n", profile_p->statcache_misses);
+ d_printf("hits: %u\n", profile_p->statcache_hits);
+
+ profile_separator("Write Cache");
+ d_printf("read_hits: %u\n", profile_p->writecache_read_hits);
+ d_printf("abutted_writes: %u\n", profile_p->writecache_abutted_writes);
+ d_printf("total_writes: %u\n", profile_p->writecache_total_writes);
+ d_printf("non_oplock_writes: %u\n", profile_p->writecache_non_oplock_writes);
+ d_printf("direct_writes: %u\n", profile_p->writecache_direct_writes);
+ d_printf("init_writes: %u\n", profile_p->writecache_init_writes);
+ d_printf("flushed_writes[SEEK]: %u\n", profile_p->writecache_flushed_writes[SEEK_FLUSH]);
+ d_printf("flushed_writes[READ]: %u\n", profile_p->writecache_flushed_writes[READ_FLUSH]);
+ d_printf("flushed_writes[WRITE]: %u\n", profile_p->writecache_flushed_writes[WRITE_FLUSH]);
+ d_printf("flushed_writes[READRAW]: %u\n", profile_p->writecache_flushed_writes[READRAW_FLUSH]);
+ d_printf("flushed_writes[OPLOCK_RELEASE]: %u\n", profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]);
+ d_printf("flushed_writes[CLOSE]: %u\n", profile_p->writecache_flushed_writes[CLOSE_FLUSH]);
+ d_printf("flushed_writes[SYNC]: %u\n", profile_p->writecache_flushed_writes[SYNC_FLUSH]);
+ d_printf("flushed_writes[SIZECHANGE]: %u\n", profile_p->writecache_flushed_writes[SIZECHANGE_FLUSH]);
+ d_printf("num_perfect_writes: %u\n", profile_p->writecache_num_perfect_writes);
+ d_printf("num_write_caches: %u\n", profile_p->writecache_num_write_caches);
+ d_printf("allocated_write_caches: %u\n", profile_p->writecache_allocated_write_caches);
+
+ profile_separator("SMB Calls");
+ d_printf("mkdir_count: %u\n", profile_p->SMBmkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->SMBmkdir_time);
+ d_printf("rmdir_count: %u\n", profile_p->SMBrmdir_count);
+ d_printf("rmdir_time: %u\n", profile_p->SMBrmdir_time);
+ d_printf("open_count: %u\n", profile_p->SMBopen_count);
+ d_printf("open_time: %u\n", profile_p->SMBopen_time);
+ d_printf("create_count: %u\n", profile_p->SMBcreate_count);
+ d_printf("create_time: %u\n", profile_p->SMBcreate_time);
+ d_printf("close_count: %u\n", profile_p->SMBclose_count);
+ d_printf("close_time: %u\n", profile_p->SMBclose_time);
+ d_printf("flush_count: %u\n", profile_p->SMBflush_count);
+ d_printf("flush_time: %u\n", profile_p->SMBflush_time);
+ d_printf("unlink_count: %u\n", profile_p->SMBunlink_count);
+ d_printf("unlink_time: %u\n", profile_p->SMBunlink_time);
+ d_printf("mv_count: %u\n", profile_p->SMBmv_count);
+ d_printf("mv_time: %u\n", profile_p->SMBmv_time);
+ d_printf("getatr_count: %u\n", profile_p->SMBgetatr_count);
+ d_printf("getatr_time: %u\n", profile_p->SMBgetatr_time);
+ d_printf("setatr_count: %u\n", profile_p->SMBsetatr_count);
+ d_printf("setatr_time: %u\n", profile_p->SMBsetatr_time);
+ d_printf("read_count: %u\n", profile_p->SMBread_count);
+ d_printf("read_time: %u\n", profile_p->SMBread_time);
+ d_printf("write_count: %u\n", profile_p->SMBwrite_count);
+ d_printf("write_time: %u\n", profile_p->SMBwrite_time);
+ d_printf("lock_count: %u\n", profile_p->SMBlock_count);
+ d_printf("lock_time: %u\n", profile_p->SMBlock_time);
+ d_printf("unlock_count: %u\n", profile_p->SMBunlock_count);
+ d_printf("unlock_time: %u\n", profile_p->SMBunlock_time);
+ d_printf("ctemp_count: %u\n", profile_p->SMBctemp_count);
+ d_printf("ctemp_time: %u\n", profile_p->SMBctemp_time);
+ d_printf("mknew_count: %u\n", profile_p->SMBmknew_count);
+ d_printf("mknew_time: %u\n", profile_p->SMBmknew_time);
+ d_printf("checkpath_count: %u\n", profile_p->SMBcheckpath_count);
+ d_printf("checkpath_time: %u\n", profile_p->SMBcheckpath_time);
+ d_printf("exit_count: %u\n", profile_p->SMBexit_count);
+ d_printf("exit_time: %u\n", profile_p->SMBexit_time);
+ d_printf("lseek_count: %u\n", profile_p->SMBlseek_count);
+ d_printf("lseek_time: %u\n", profile_p->SMBlseek_time);
+ d_printf("lockread_count: %u\n", profile_p->SMBlockread_count);
+ d_printf("lockread_time: %u\n", profile_p->SMBlockread_time);
+ d_printf("writeunlock_count: %u\n", profile_p->SMBwriteunlock_count);
+ d_printf("writeunlock_time: %u\n", profile_p->SMBwriteunlock_time);
+ d_printf("readbraw_count: %u\n", profile_p->SMBreadbraw_count);
+ d_printf("readbraw_time: %u\n", profile_p->SMBreadbraw_time);
+ d_printf("readBmpx_count: %u\n", profile_p->SMBreadBmpx_count);
+ d_printf("readBmpx_time: %u\n", profile_p->SMBreadBmpx_time);
+ d_printf("readBs_count: %u\n", profile_p->SMBreadBs_count);
+ d_printf("readBs_time: %u\n", profile_p->SMBreadBs_time);
+ d_printf("writebraw_count: %u\n", profile_p->SMBwritebraw_count);
+ d_printf("writebraw_time: %u\n", profile_p->SMBwritebraw_time);
+ d_printf("writeBmpx_count: %u\n", profile_p->SMBwriteBmpx_count);
+ d_printf("writeBmpx_time: %u\n", profile_p->SMBwriteBmpx_time);
+ d_printf("writeBs_count: %u\n", profile_p->SMBwriteBs_count);
+ d_printf("writeBs_time: %u\n", profile_p->SMBwriteBs_time);
+ d_printf("writec_count: %u\n", profile_p->SMBwritec_count);
+ d_printf("writec_time: %u\n", profile_p->SMBwritec_time);
+ d_printf("setattrE_count: %u\n", profile_p->SMBsetattrE_count);
+ d_printf("setattrE_time: %u\n", profile_p->SMBsetattrE_time);
+ d_printf("getattrE_count: %u\n", profile_p->SMBgetattrE_count);
+ d_printf("getattrE_time: %u\n", profile_p->SMBgetattrE_time);
+ d_printf("lockingX_count: %u\n", profile_p->SMBlockingX_count);
+ d_printf("lockingX_time: %u\n", profile_p->SMBlockingX_time);
+ d_printf("trans_count: %u\n", profile_p->SMBtrans_count);
+ d_printf("trans_time: %u\n", profile_p->SMBtrans_time);
+ d_printf("transs_count: %u\n", profile_p->SMBtranss_count);
+ d_printf("transs_time: %u\n", profile_p->SMBtranss_time);
+ d_printf("ioctl_count: %u\n", profile_p->SMBioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->SMBioctl_time);
+ d_printf("ioctls_count: %u\n", profile_p->SMBioctls_count);
+ d_printf("ioctls_time: %u\n", profile_p->SMBioctls_time);
+ d_printf("copy_count: %u\n", profile_p->SMBcopy_count);
+ d_printf("copy_time: %u\n", profile_p->SMBcopy_time);
+ d_printf("move_count: %u\n", profile_p->SMBmove_count);
+ d_printf("move_time: %u\n", profile_p->SMBmove_time);
+ d_printf("echo_count: %u\n", profile_p->SMBecho_count);
+ d_printf("echo_time: %u\n", profile_p->SMBecho_time);
+ d_printf("writeclose_count: %u\n", profile_p->SMBwriteclose_count);
+ d_printf("writeclose_time: %u\n", profile_p->SMBwriteclose_time);
+ d_printf("openX_count: %u\n", profile_p->SMBopenX_count);
+ d_printf("openX_time: %u\n", profile_p->SMBopenX_time);
+ d_printf("readX_count: %u\n", profile_p->SMBreadX_count);
+ d_printf("readX_time: %u\n", profile_p->SMBreadX_time);
+ d_printf("writeX_count: %u\n", profile_p->SMBwriteX_count);
+ d_printf("writeX_time: %u\n", profile_p->SMBwriteX_time);
+ d_printf("trans2_count: %u\n", profile_p->SMBtrans2_count);
+ d_printf("trans2_time: %u\n", profile_p->SMBtrans2_time);
+ d_printf("transs2_count: %u\n", profile_p->SMBtranss2_count);
+ d_printf("transs2_time: %u\n", profile_p->SMBtranss2_time);
+ d_printf("findclose_count: %u\n", profile_p->SMBfindclose_count);
+ d_printf("findclose_time: %u\n", profile_p->SMBfindclose_time);
+ d_printf("findnclose_count: %u\n", profile_p->SMBfindnclose_count);
+ d_printf("findnclose_time: %u\n", profile_p->SMBfindnclose_time);
+ d_printf("tcon_count: %u\n", profile_p->SMBtcon_count);
+ d_printf("tcon_time: %u\n", profile_p->SMBtcon_time);
+ d_printf("tdis_count: %u\n", profile_p->SMBtdis_count);
+ d_printf("tdis_time: %u\n", profile_p->SMBtdis_time);
+ d_printf("negprot_count: %u\n", profile_p->SMBnegprot_count);
+ d_printf("negprot_time: %u\n", profile_p->SMBnegprot_time);
+ d_printf("sesssetupX_count: %u\n", profile_p->SMBsesssetupX_count);
+ d_printf("sesssetupX_time: %u\n", profile_p->SMBsesssetupX_time);
+ d_printf("ulogoffX_count: %u\n", profile_p->SMBulogoffX_count);
+ d_printf("ulogoffX_time: %u\n", profile_p->SMBulogoffX_time);
+ d_printf("tconX_count: %u\n", profile_p->SMBtconX_count);
+ d_printf("tconX_time: %u\n", profile_p->SMBtconX_time);
+ d_printf("dskattr_count: %u\n", profile_p->SMBdskattr_count);
+ d_printf("dskattr_time: %u\n", profile_p->SMBdskattr_time);
+ d_printf("search_count: %u\n", profile_p->SMBsearch_count);
+ d_printf("search_time: %u\n", profile_p->SMBsearch_time);
+ d_printf("ffirst_count: %u\n", profile_p->SMBffirst_count);
+ d_printf("ffirst_time: %u\n", profile_p->SMBffirst_time);
+ d_printf("funique_count: %u\n", profile_p->SMBfunique_count);
+ d_printf("funique_time: %u\n", profile_p->SMBfunique_time);
+ d_printf("fclose_count: %u\n", profile_p->SMBfclose_count);
+ d_printf("fclose_time: %u\n", profile_p->SMBfclose_time);
+ d_printf("nttrans_count: %u\n", profile_p->SMBnttrans_count);
+ d_printf("nttrans_time: %u\n", profile_p->SMBnttrans_time);
+ d_printf("nttranss_count: %u\n", profile_p->SMBnttranss_count);
+ d_printf("nttranss_time: %u\n", profile_p->SMBnttranss_time);
+ d_printf("ntcreateX_count: %u\n", profile_p->SMBntcreateX_count);
+ d_printf("ntcreateX_time: %u\n", profile_p->SMBntcreateX_time);
+ d_printf("ntcancel_count: %u\n", profile_p->SMBntcancel_count);
+ d_printf("ntcancel_time: %u\n", profile_p->SMBntcancel_time);
+ d_printf("splopen_count: %u\n", profile_p->SMBsplopen_count);
+ d_printf("splopen_time: %u\n", profile_p->SMBsplopen_time);
+ d_printf("splwr_count: %u\n", profile_p->SMBsplwr_count);
+ d_printf("splwr_time: %u\n", profile_p->SMBsplwr_time);
+ d_printf("splclose_count: %u\n", profile_p->SMBsplclose_count);
+ d_printf("splclose_time: %u\n", profile_p->SMBsplclose_time);
+ d_printf("splretq_count: %u\n", profile_p->SMBsplretq_count);
+ d_printf("splretq_time: %u\n", profile_p->SMBsplretq_time);
+ d_printf("sends_count: %u\n", profile_p->SMBsends_count);
+ d_printf("sends_time: %u\n", profile_p->SMBsends_time);
+ d_printf("sendb_count: %u\n", profile_p->SMBsendb_count);
+ d_printf("sendb_time: %u\n", profile_p->SMBsendb_time);
+ d_printf("fwdname_count: %u\n", profile_p->SMBfwdname_count);
+ d_printf("fwdname_time: %u\n", profile_p->SMBfwdname_time);
+ d_printf("cancelf_count: %u\n", profile_p->SMBcancelf_count);
+ d_printf("cancelf_time: %u\n", profile_p->SMBcancelf_time);
+ d_printf("getmac_count: %u\n", profile_p->SMBgetmac_count);
+ d_printf("getmac_time: %u\n", profile_p->SMBgetmac_time);
+ d_printf("sendstrt_count: %u\n", profile_p->SMBsendstrt_count);
+ d_printf("sendstrt_time: %u\n", profile_p->SMBsendstrt_time);
+ d_printf("sendend_count: %u\n", profile_p->SMBsendend_count);
+ d_printf("sendend_time: %u\n", profile_p->SMBsendend_time);
+ d_printf("sendtxt_count: %u\n", profile_p->SMBsendtxt_count);
+ d_printf("sendtxt_time: %u\n", profile_p->SMBsendtxt_time);
+ d_printf("invalid_count: %u\n", profile_p->SMBinvalid_count);
+ d_printf("invalid_time: %u\n", profile_p->SMBinvalid_time);
+
+ profile_separator("Pathworks Calls");
+ d_printf("setdir_count: %u\n", profile_p->pathworks_setdir_count);
+ d_printf("setdir_time: %u\n", profile_p->pathworks_setdir_time);
+
+ profile_separator("Trans2 Calls");
+ d_printf("open_count: %u\n", profile_p->Trans2_open_count);
+ d_printf("open_time: %u\n", profile_p->Trans2_open_time);
+ d_printf("findfirst_count: %u\n", profile_p->Trans2_findfirst_count);
+ d_printf("findfirst_time: %u\n", profile_p->Trans2_findfirst_time);
+ d_printf("findnext_count: %u\n", profile_p->Trans2_findnext_count);
+ d_printf("findnext_time: %u\n", profile_p->Trans2_findnext_time);
+ d_printf("qfsinfo_count: %u\n", profile_p->Trans2_qfsinfo_count);
+ d_printf("qfsinfo_time: %u\n", profile_p->Trans2_qfsinfo_time);
+ d_printf("setfsinfo_count: %u\n", profile_p->Trans2_setfsinfo_count);
+ d_printf("setfsinfo_time: %u\n", profile_p->Trans2_setfsinfo_time);
+ d_printf("qpathinfo_count: %u\n", profile_p->Trans2_qpathinfo_count);
+ d_printf("qpathinfo_time: %u\n", profile_p->Trans2_qpathinfo_time);
+ d_printf("setpathinfo_count: %u\n", profile_p->Trans2_setpathinfo_count);
+ d_printf("setpathinfo_time: %u\n", profile_p->Trans2_setpathinfo_time);
+ d_printf("qfileinfo_count: %u\n", profile_p->Trans2_qfileinfo_count);
+ d_printf("qfileinfo_time: %u\n", profile_p->Trans2_qfileinfo_time);
+ d_printf("setfileinfo_count: %u\n", profile_p->Trans2_setfileinfo_count);
+ d_printf("setfileinfo_time: %u\n", profile_p->Trans2_setfileinfo_time);
+ d_printf("fsctl_count: %u\n", profile_p->Trans2_fsctl_count);
+ d_printf("fsctl_time: %u\n", profile_p->Trans2_fsctl_time);
+ d_printf("ioctl_count: %u\n", profile_p->Trans2_ioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->Trans2_ioctl_time);
+ d_printf("findnotifyfirst_count: %u\n", profile_p->Trans2_findnotifyfirst_count);
+ d_printf("findnotifyfirst_time: %u\n", profile_p->Trans2_findnotifyfirst_time);
+ d_printf("findnotifynext_count: %u\n", profile_p->Trans2_findnotifynext_count);
+ d_printf("findnotifynext_time: %u\n", profile_p->Trans2_findnotifynext_time);
+ d_printf("mkdir_count: %u\n", profile_p->Trans2_mkdir_count);
+ d_printf("mkdir_time: %u\n", profile_p->Trans2_mkdir_time);
+ d_printf("session_setup_count: %u\n", profile_p->Trans2_session_setup_count);
+ d_printf("session_setup_time: %u\n", profile_p->Trans2_session_setup_time);
+ d_printf("get_dfs_referral_count: %u\n", profile_p->Trans2_get_dfs_referral_count);
+ d_printf("get_dfs_referral_time: %u\n", profile_p->Trans2_get_dfs_referral_time);
+ d_printf("report_dfs_inconsistancy_count: %u\n", profile_p->Trans2_report_dfs_inconsistancy_count);
+ d_printf("report_dfs_inconsistancy_time: %u\n", profile_p->Trans2_report_dfs_inconsistancy_time);
+
+ profile_separator("NT Transact Calls");
+ d_printf("create_count: %u\n", profile_p->NT_transact_create_count);
+ d_printf("create_time: %u\n", profile_p->NT_transact_create_time);
+ d_printf("ioctl_count: %u\n", profile_p->NT_transact_ioctl_count);
+ d_printf("ioctl_time: %u\n", profile_p->NT_transact_ioctl_time);
+ d_printf("set_security_desc_count: %u\n", profile_p->NT_transact_set_security_desc_count);
+ d_printf("set_security_desc_time: %u\n", profile_p->NT_transact_set_security_desc_time);
+ d_printf("notify_change_count: %u\n", profile_p->NT_transact_notify_change_count);
+ d_printf("notify_change_time: %u\n", profile_p->NT_transact_notify_change_time);
+ d_printf("rename_count: %u\n", profile_p->NT_transact_rename_count);
+ d_printf("rename_time: %u\n", profile_p->NT_transact_rename_time);
+ d_printf("query_security_desc_count: %u\n", profile_p->NT_transact_query_security_desc_count);
+ d_printf("query_security_desc_time: %u\n", profile_p->NT_transact_query_security_desc_time);
+
+ profile_separator("ACL Calls");
+ d_printf("get_nt_acl_count: %u\n", profile_p->get_nt_acl_count);
+ d_printf("get_nt_acl_time: %u\n", profile_p->get_nt_acl_time);
+ d_printf("fget_nt_acl_count: %u\n", profile_p->fget_nt_acl_count);
+ d_printf("fget_nt_acl_time: %u\n", profile_p->fget_nt_acl_time);
+ d_printf("set_nt_acl_count: %u\n", profile_p->set_nt_acl_count);
+ d_printf("set_nt_acl_time: %u\n", profile_p->set_nt_acl_time);
+ d_printf("fset_nt_acl_count: %u\n", profile_p->fset_nt_acl_count);
+ d_printf("fset_nt_acl_time: %u\n", profile_p->fset_nt_acl_time);
+ d_printf("chmod_acl_count: %u\n", profile_p->chmod_acl_count);
+ d_printf("chmod_acl_time: %u\n", profile_p->chmod_acl_time);
+ d_printf("fchmod_acl_count: %u\n", profile_p->fchmod_acl_count);
+ d_printf("fchmod_acl_time: %u\n", profile_p->fchmod_acl_time);
+
+ profile_separator("NMBD Calls");
+ d_printf("name_release_count: %u\n", profile_p->name_release_count);
+ d_printf("name_release_time: %u\n", profile_p->name_release_time);
+ d_printf("name_refresh_count: %u\n", profile_p->name_refresh_count);
+ d_printf("name_refresh_time: %u\n", profile_p->name_refresh_time);
+ d_printf("name_registration_count: %u\n", profile_p->name_registration_count);
+ d_printf("name_registration_time: %u\n", profile_p->name_registration_time);
+ d_printf("node_status_count: %u\n", profile_p->node_status_count);
+ d_printf("node_status_time: %u\n", profile_p->node_status_time);
+ d_printf("name_query_count: %u\n", profile_p->name_query_count);
+ d_printf("name_query_time: %u\n", profile_p->name_query_time);
+ d_printf("host_announce_count: %u\n", profile_p->host_announce_count);
+ d_printf("host_announce_time: %u\n", profile_p->host_announce_time);
+ d_printf("workgroup_announce_count: %u\n", profile_p->workgroup_announce_count);
+ d_printf("workgroup_announce_time: %u\n", profile_p->workgroup_announce_time);
+ d_printf("local_master_announce_count: %u\n", profile_p->local_master_announce_count);
+ d_printf("local_master_announce_time: %u\n", profile_p->local_master_announce_time);
+ d_printf("master_browser_announce_count: %u\n", profile_p->master_browser_announce_count);
+ d_printf("master_browser_announce_time: %u\n", profile_p->master_browser_announce_time);
+ d_printf("lm_host_announce_count: %u\n", profile_p->lm_host_announce_count);
+ d_printf("lm_host_announce_time: %u\n", profile_p->lm_host_announce_time);
+ d_printf("get_backup_list_count: %u\n", profile_p->get_backup_list_count);
+ d_printf("get_backup_list_time: %u\n", profile_p->get_backup_list_time);
+ d_printf("reset_browser_count: %u\n", profile_p->reset_browser_count);
+ d_printf("reset_browser_time: %u\n", profile_p->reset_browser_time);
+ d_printf("announce_request_count: %u\n", profile_p->announce_request_count);
+ d_printf("announce_request_time: %u\n", profile_p->announce_request_time);
+ d_printf("lm_announce_request_count: %u\n", profile_p->lm_announce_request_count);
+ d_printf("lm_announce_request_time: %u\n", profile_p->lm_announce_request_time);
+ d_printf("domain_logon_count: %u\n", profile_p->domain_logon_count);
+ d_printf("domain_logon_time: %u\n", profile_p->domain_logon_time);
+ d_printf("sync_browse_lists_count: %u\n", profile_p->sync_browse_lists_count);
+ d_printf("sync_browse_lists_time: %u\n", profile_p->sync_browse_lists_time);
+ d_printf("run_elections_count: %u\n", profile_p->run_elections_count);
+ d_printf("run_elections_time: %u\n", profile_p->run_elections_time);
+ d_printf("election_count: %u\n", profile_p->election_count);
+ d_printf("election_time: %u\n", profile_p->election_time);
+#else /* WITH_PROFILE */
+ fprintf(stderr, "Profile data unavailable\n");
+#endif /* WITH_PROFILE */
+
+ return True;
+}
+
+#ifdef WITH_PROFILE
+
+/* Convert microseconds to milliseconds. */
+#define usec_to_msec(s) ((s) / 1000)
+/* Convert microseconds to seconds. */
+#define usec_to_sec(s) ((s) / 1000000)
+/* One second in microseconds. */
+#define one_second_usec (1000000)
+
+#define sample_interval_usec one_second_usec
+
+#define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
+
+static int print_count_samples(
+ const struct profile_stats * const current,
+ const struct profile_stats * const last,
+ SMB_BIG_UINT delta_usec)
+{
+ int i;
+ int count = 0;
+ unsigned step;
+ SMB_BIG_UINT spent;
+ int delta_sec;
+ const char * name;
+ char buf[40];
+
+ if (delta_usec == 0) {
+ return 0;
+ }
+
+ buf[0] = '\0';
+ delta_sec = usec_to_sec(delta_usec);
+
+ for (i = 0; i < PR_VALUE_MAX; ++i) {
+ step = current->count[i] - last->count[i];
+ spent = current->time[i] - last->time[i];
+
+ if (step) {
+ ++count;
+
+ name = profile_value_name(i);
+
+ if (buf[0] == '\0') {
+ snprintf(buf, sizeof(buf),
+ "%s %d/sec (%.2f%%)",
+ name, step / delta_sec,
+ percent_time(spent, delta_usec));
+ } else {
+ printf("%-40s %s %d/sec (%.2f%%)\n",
+ buf, name, step / delta_sec,
+ percent_time(spent, delta_usec));
+ buf[0] = '\0';
+ }
+ }
+ }
+
+ return count;
+}
+
+static struct profile_stats sample_data[2];
+static SMB_BIG_UINT sample_time[2];
+
+BOOL status_profile_rates(BOOL verbose)
+{
+ SMB_BIG_UINT remain_usec;
+ SMB_BIG_UINT next_usec;
+ SMB_BIG_UINT delta_usec;
+
+ int last = 0;
+ int current = 1;
+ int tmp;
+
+ if (verbose) {
+ fprintf(stderr, "Sampling stats at %d sec intervals\n",
+ usec_to_sec(sample_interval_usec));
+ }
+
+ if (!profile_setup(True)) {
+ fprintf(stderr,"Failed to initialise profile memory\n");
+ return False;
+ }
+
+ memcpy(&sample_data[last], profile_p, sizeof(*profile_p));
+ for (;;) {
+ sample_time[current] = profile_timestamp();
+ next_usec = sample_time[current] + sample_interval_usec;
+
+ /* Take a sample. */
+ memcpy(&sample_data[current], profile_p, sizeof(*profile_p));
+
+ /* Rate convert some values and print results. */
+ delta_usec = sample_time[current] - sample_time[last];
+
+ if (print_count_samples(&sample_data[current],
+ &sample_data[last], delta_usec)) {
+ printf("\n");
+ }
+
+ /* Swap sampling buffers. */
+ tmp = last;
+ last = current;
+ current = tmp;
+
+ /* Delay until next sample time. */
+ remain_usec = next_usec - profile_timestamp();
+ if (remain_usec > sample_interval_usec) {
+ fprintf(stderr, "eek! falling behind sampling rate!\n");
+ } else {
+ if (verbose) {
+ fprintf(stderr,
+ "delaying for %lu msec\n",
+ (unsigned long )usec_to_msec(remain_usec));
+ }
+
+ sys_usleep(remain_usec);
+ }
+
+ }
+
+ return True;
+}
+
+#else /* WITH_PROFILE */
+
+BOOL status_profile_rates(BOOL verbose)
+{
+ fprintf(stderr, "Profile data unavailable\n");
+ return False;
+}
+
+#endif /* WITH_PROFILE */
+
diff --git a/source/web/diagnose.c b/source/web/diagnose.c
index d259717da0b..b53e139ca94 100644
--- a/source/web/diagnose.c
+++ b/source/web/diagnose.c
@@ -60,16 +60,16 @@ BOOL nmbd_running(void)
then closing it */
BOOL smbd_running(void)
{
- static struct cli_state cli;
+ struct cli_state *cli;
- if (!cli_initialise(&cli))
+ if ((cli = cli_initialise()) == NULL)
return False;
- if (!cli_connect(&cli, global_myname(), &loopback_ip)) {
- cli_shutdown(&cli);
+ if (!cli_connect(cli, global_myname(), &loopback_ip)) {
+ cli_shutdown(cli);
return False;
}
- cli_shutdown(&cli);
+ cli_shutdown(cli);
return True;
}
diff --git a/source/web/neg_lang.c b/source/web/neg_lang.c
index fb79f41f13c..207614655db 100644
--- a/source/web/neg_lang.c
+++ b/source/web/neg_lang.c
@@ -57,8 +57,8 @@ 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;
if (a->pri > b->pri) return -1;
- if (a->pri == b->pri) return 0;
- return 1;
+ if (a->pri < b->pri) return 1;
+ return 0;
}
/*
diff --git a/source/web/statuspage.c b/source/web/statuspage.c
index cb6fa911711..459b679d817 100644
--- a/source/web/statuspage.c
+++ b/source/web/statuspage.c
@@ -106,7 +106,10 @@ static char *tstring(time_t t)
return buf;
}
-static void print_share_mode(const struct share_mode_entry *e, const char *sharepath, const char *fname)
+static void print_share_mode(const struct share_mode_entry *e,
+ const char *sharepath,
+ const char *fname,
+ void *dummy)
{
char *utf8_fname;
int deny_mode;
@@ -434,7 +437,7 @@ void status_page(void)
printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n", _("PID"), _("Sharing"), _("R/W"), _("Oplock"), _("File"), _("Date"));
locking_init(1);
- share_mode_forall(print_share_mode);
+ share_mode_forall(print_share_mode, NULL);
locking_end();
printf("</table>\n");
diff --git a/source/web/swat.c b/source/web/swat.c
index d1fd0b4f9bc..d43f8941bc1 100644
--- a/source/web/swat.c
+++ b/source/web/swat.c
@@ -432,7 +432,7 @@ static void write_config(FILE *f, BOOL show_defaults)
{
fprintf(f, "# Samba config file created using SWAT\n");
fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
- fprintf(f, "# Date: %s\n\n", timestring(False));
+ fprintf(f, "# Date: %s\n\n", current_timestring(False));
lp_dump(f, show_defaults, iNumNonAutoPrintServices);
}